TestRunner.py revision 1befb9b2df7b287872021518cedce4a0aeca3b95
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 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 executeCommand(command, cwd=None, env=None): 25be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar p = subprocess.Popen(command, cwd=cwd, 26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdin=subprocess.PIPE, 27be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdout=subprocess.PIPE, 28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderr=subprocess.PIPE, 29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar env=env) 30be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out,err = p.communicate() 31be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = p.wait() 32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Detect Ctrl-C in subprocess. 34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if exitCode == -signal.SIGINT: 35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise KeyboardInterrupt 36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return out, err, exitCode 38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results): 40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if isinstance(cmd, ShUtil.Seq): 41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == ';': 42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return executeShCmd(cmd.rhs, cfg, cwd, results) 44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '&': 46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise NotImplementedError,"unsupported test command: '&'" 47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 48be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '||': 49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res != 0: 51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.rhs, cfg, cwd, results) 52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 53be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '&&': 54be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res is None: 56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 57be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res == 0: 59be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.rhs, cfg, cwd, results) 60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 61be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 62be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise ValueError,'Unknown shell command: %r' % cmd.op 63be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar assert isinstance(cmd, ShUtil.Pipeline) 65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs = [] 66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = subprocess.PIPE 675a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderrTempFiles = [] 68c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar opened_files = [] 691befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar named_temp_files = [] 705a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # To avoid deadlock, we use a single stderr stream for piped 715a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # output. This is null until we have seen some output using 725a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # stderr. 735a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar for i,j in enumerate(cmd.commands): 74a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # Apply the redirections, we use (N,) as a sentinal to indicate stdin, 75a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or 76a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # from a file are represented with a list [file, mode, file-object] 77a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # where file-object is initially None. 78be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects = [(0,), (1,), (2,)] 79be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for r in j.redirects: 80be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r[0] == ('>',2): 81be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[2] = [r[1], 'w', None] 82a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar elif r[0] == ('>>',2): 83a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar redirects[2] = [r[1], 'a', None] 84be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>&',2) and r[1] in '012': 85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[2] = redirects[int(r[1])] 86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>&',) or r[0] == ('&>',): 87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[1] = redirects[2] = [r[1], 'w', None] 88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>',): 89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[1] = [r[1], 'w', None] 90a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar elif r[0] == ('>>',): 91a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar redirects[1] = [r[1], 'a', None] 92be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('<',): 93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[0] = [r[1], 'r', None] 94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise NotImplementedError,"Unsupported redirect: %r" % (r,) 96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 97a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # Map from the final redirections to something subprocess can handle. 98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar final_redirects = [] 99be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for index,r in enumerate(redirects): 100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r == (0,): 101be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = input 102be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r == (1,): 103be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if index == 0: 104be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise NotImplementedError,"Unsupported redirect for stdin" 105be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif index == 1: 106be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.PIPE 107be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 108be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.STDOUT 109be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r == (2,): 110be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if index != 2: 111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise NotImplementedError,"Unsupported redirect on stdout" 112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.PIPE 113be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r[2] is None: 1156efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar if kAvoidDevNull and r[0] == '/dev/null': 1166efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar r[2] = tempfile.TemporaryFile(mode=r[1]) 1176efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar else: 1186efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar r[2] = open(r[0], r[1]) 119474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar # Workaround a Win32 and/or subprocess bug when appending. 120e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar # 121e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar # FIXME: Actually, this is probably an instance of PR6753. 122474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar if r[1] == 'a': 123bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar r[2].seek(0, 2) 124c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar opened_files.append(r[2]) 125be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = r[2] 126be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar final_redirects.append(result) 127be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 128be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdin, stdout, stderr = final_redirects 129be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 130be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # If stderr wants to come from stdout, but stdout isn't a pipe, then put 131be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # stderr on a pipe and treat it as stdout. 132be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE): 133be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderr = subprocess.PIPE 134be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderrIsStdout = True 135be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 136be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderrIsStdout = False 1376bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar 1385a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # Don't allow stderr on a PIPE except for the last 1395a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # process, this could deadlock. 1405a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # 1415a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # FIXME: This is slow, but so is deadlock. 1425a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar if stderr == subprocess.PIPE and j != cmd.commands[-1]: 1435a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderr = tempfile.TemporaryFile(mode='w+b') 1445a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderrTempFiles.append((i, stderr)) 1455a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar 1466bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar # Resolve the executable path ourselves. 1476bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar args = list(j.args) 1486bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar args[0] = Util.which(args[0], cfg.environment['PATH']) 1496bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar if not args[0]: 1506bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar raise InternalShellError(j, '%r: command not found' % j.args[0]) 1516bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar 1521befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar # Replace uses of /dev/null with temporary files. 1531befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar if kAvoidDevNull: 1541befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar for i,arg in enumerate(args): 1551befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar if arg == "/dev/null": 1561befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar f = tempfile.NamedTemporaryFile(delete=False) 1571befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar f.close() 1581befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar named_temp_files.append(f.name) 1591befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar args[i] = f.name 1601befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar 1614b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar procs.append(subprocess.Popen(args, cwd=cwd, 162be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdin = stdin, 163be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdout = stdout, 164be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderr = stderr, 165be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar env = cfg.environment, 16658c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar close_fds = kUseCloseFDs)) 167be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 168be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Immediately close stdin for any process taking stdin from us. 169be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if stdin == subprocess.PIPE: 170be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs[-1].stdin.close() 171be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs[-1].stdin = None 172be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 173be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Update the current stdin source. 174be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if stdout == subprocess.PIPE: 175be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = procs[-1].stdout 176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif stderrIsStdout: 177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = procs[-1].stderr 178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = subprocess.PIPE 180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 1815a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # FIXME: There is probably still deadlock potential here. Yawn. 182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData = [None] * len(procs) 183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData[-1] = procs[-1].communicate() 1845a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar 185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i in range(len(procs) - 1): 186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if procs[i].stdout is not None: 187be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = procs[i].stdout.read() 188be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 189be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = '' 190be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if procs[i].stderr is not None: 191be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar err = procs[i].stderr.read() 192be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 193be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar err = '' 194be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData[i] = (out,err) 195c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar 1965a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # Read stderr out of the temp files. 1975a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar for i,f in stderrTempFiles: 1985a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar f.seek(0, 0) 1995a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar procData[i] = (procData[i][0], f.read()) 200be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = None 202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i,(out,err) in enumerate(procData): 203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = procs[i].wait() 204be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Detect Ctrl-C in subprocess. 205be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res == -signal.SIGINT: 206be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise KeyboardInterrupt 207be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 208be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar results.append((cmd.commands[i], out, err, res)) 209be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.pipe_err: 210be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Python treats the exit code as a signed char. 211be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res < 0: 212be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = min(exitCode, res) 213be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 214be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = max(exitCode, res) 215be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 216be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = res 217be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 218c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar # Explicitly close any redirected files. 219c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar for f in opened_files: 220c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar f.close() 221c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar 2221befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar # Remove any named temporary files we created. 2231befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar for f in named_temp_files: 2241befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar try: 2251befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar os.remove(f) 2261befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar except OSError: 2271befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar pass 2281befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar 229be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.negate: 230be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = not exitCode 231be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 232be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return exitCode 233be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 234be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd): 235be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = ' &&\n'.join(commands) 236be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar try: 237be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmd = ShUtil.ShParser(ln, litConfig.isWindows).parse() 238be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar except: 239be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.FAIL, "shell parser error on: %r" % ln) 240be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 241be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar results = [] 2426bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar try: 2436bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar exitCode = executeShCmd(cmd, test.config, cwd, results) 2446bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar except InternalShellError,e: 2456bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar out = '' 2466bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar err = e.message 2476bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar exitCode = 255 248be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 249be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = err = '' 250be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i,(cmd, cmd_out,cmd_err,res) in enumerate(results): 251be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args)) 252be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Result: %r\n' % (i, res) 253be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Output:\n%s\n\n' % (i, cmd_out) 254be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err) 255be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 256be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return out, err, exitCode 257be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd): 259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar import TclUtil 260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmds = [] 261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for ln in commands: 262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Given the unfortunate way LLVM's test are written, the line gets 263be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # backslash substitution done twice. 264be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True) 265be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar try: 267be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar tokens = list(TclUtil.TclLexer(ln).lex()) 268be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar except: 269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.FAIL, "Tcl lexer error on: %r" % ln) 270be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 271be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Validate there are no control tokens. 272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for t in tokens: 273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not isinstance(t, str): 274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.FAIL, 275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar "Invalid test line: %r containing %r" % (ln, t)) 276be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 277be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar try: 278be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline()) 279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar except: 2802c0a49c8cba8b7a6624d9c0b96f7d94231e10d22Daniel Dunbar return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln) 281be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 282b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin if litConfig.useValgrind: 283b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin for pipeline in cmds: 284b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin if pipeline.commands: 285b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin # Only valgrind the first command in each pipeline, to avoid 286b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin # valgrinding things like grep, not, and FileCheck. 287b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin cmd = pipeline.commands[0] 28832989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin cmd.args = litConfig.valgrindArgs + cmd.args 289b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin 290be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmd = cmds[0] 291be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for c in cmds[1:]: 292be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmd = ShUtil.Seq(cmd, '&&', c) 293be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 2947723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar # FIXME: This is lame, we shouldn't need bash. See PR5240. 2957723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar bashPath = litConfig.getBashPath() 2967723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar if litConfig.useTclAsSh and bashPath: 297be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = tmpBase + '.script' 298be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 299be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Write script file 300be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f = open(script,'w') 301be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>f, 'set -o pipefail' 302be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar cmd.toShell(f, pipefail = True) 303be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.close() 304be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 305be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if 0: 306be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>sys.stdout, cmd 307be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>sys.stdout, open(script).read() 308be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>sys.stdout 309be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return '', '', 0 310be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 3117723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar command = [litConfig.getBashPath(), script] 312be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out,err,exitCode = executeCommand(command, cwd=cwd, 313be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar env=test.config.environment) 314be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 315be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Tcl commands fail on standard error output. 316be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if err: 317be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = 1 318be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = 'Command has output on stderr!\n\n' + out 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 # Tcl commands fail on standard error output. 332be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if [True for _,_,err,res in results if err]: 333be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = 1 334be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command has output on stderr!\n\n' 335be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 336be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i,(cmd, cmd_out, cmd_err, res) in enumerate(results): 337be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args)) 338be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Result: %r\n' % (i, res) 339be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Output:\n%s\n\n' % (i, cmd_out) 340be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err) 341be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 342be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return out, err, exitCode 343be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 344be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd): 345be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = tmpBase + '.script' 346be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.isWindows: 347be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script += '.bat' 348be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 349be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Write script file 350be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f = open(script,'w') 351be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.isWindows: 352be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands)) 353be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 354be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.write(' &&\n'.join(commands)) 355be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.write('\n') 356be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.close() 357be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 358be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.isWindows: 359be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar command = ['cmd','/c', script] 360be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 361be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 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) 400be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar tmpBase = os.path.join(execdir, 'Output', execbase) 40140c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar if test.index is not None: 40240c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar tmpBase += '_%d' % test.index 403be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 404f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar # Normalize slashes, if requested. 405f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar if normalize_slashes: 406f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar sourcepath = sourcepath.replace('\\', '/') 407f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar sourcedir = sourcedir.replace('\\', '/') 408f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar tmpBase = tmpBase.replace('\\', '/') 409f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar 410be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # We use #_MARKER_# to hide %% while we do the other substitutions. 411be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar substitutions = [('%%', '#_MARKER_#')] 412be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar substitutions.extend(test.config.substitutions) 413be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar substitutions.extend([('%s', sourcepath), 414f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar ('%S', sourcedir), 415f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar ('%p', sourcedir), 416be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ('%t', tmpBase + '.tmp'), 4175110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar # FIXME: Remove this once we kill DejaGNU. 4185110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar ('%abs_tmp', tmpBase + '.tmp'), 419be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ('#_MARKER_#', '%')]) 420be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 421be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Collect the test lines from the script. 422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = [] 423be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar xfails = [] 424be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar xtargets = [] 425be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for ln in open(sourcepath): 426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if 'RUN:' in ln: 427be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Isolate the command to run. 428be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar index = ln.index('RUN:') 429be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = ln[index+4:] 430be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 431be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Trim trailing whitespace. 432be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = ln.rstrip() 433be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 434be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Collapse lines with trailing '\\'. 435be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if script and script[-1][-1] == '\\': 436be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script[-1] = script[-1][:-1] + ln 437be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 438be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script.append(ln) 43942543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar elif 'XFAIL:' in ln: 440be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar items = ln[ln.index('XFAIL:') + 6:].split(',') 441be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar xfails.extend([s.strip() for s in items]) 442be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif 'XTARGET:' in ln: 443be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar items = ln[ln.index('XTARGET:') + 8:].split(',') 444be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar xtargets.extend([s.strip() for s in items]) 445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif 'END.' in ln: 446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Check for END. lines. 447be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if ln[ln.index('END.'):].strip() == 'END.': 448be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar break 449be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 450be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Apply substitutions to the script. 451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def processLine(ln): 452be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Apply substitutions 453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for a,b in substitutions: 454be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = ln.replace(a,b) 455be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 456be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Strip the trailing newline and any extra whitespace. 457be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return ln.strip() 458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = map(processLine, script) 459be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 460be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Verify the script contains a run line. 461be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not script: 462be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.UNRESOLVED, "Test has no run line!") 463be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 464be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if script[-1][-1] == '\\': 465be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')") 466be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 46742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar isXFail = isExpectedFail(xfails, xtargets, test.suite.config.target_triple) 46842543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar return script,isXFail,tmpBase,execdir 469be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 470be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef formatTestOutput(status, out, err, exitCode, script): 471be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar output = StringIO.StringIO() 472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "Script:" 473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 474be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, '\n'.join(script) 475be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 476be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "Exit Code: %r" % exitCode 477be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "Command Output (stdout):" 478be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 479be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar output.write(out) 480be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 481be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "Command Output (stderr):" 482be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 483be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar output.write(err) 484be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar print >>output, "--" 485be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (status, output.getvalue()) 486be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 487be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclTest(test, litConfig): 488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if test.config.unsupported: 489be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.UNSUPPORTED, 'Test is unsupported') 490be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 491f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar # Parse the test script, normalizing slashes in substitutions on Windows 492f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar # (since otherwise Tcl style lexing will treat them as escapes). 493f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows) 494be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if len(res) == 2: 495be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 496be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 49742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar script, isXFail, tmpBase, execdir = res 498be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 499be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.noExecute: 500be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.PASS, '') 501be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 502be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Create the output directory if it does not already exist. 503be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar Util.mkdir_p(os.path.dirname(tmpBase)) 504be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 505be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir) 506be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if len(res) == 2: 507be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 508be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 509be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out,err,exitCode = res 510be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if isXFail: 511be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ok = exitCode != 0 512be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar status = (Test.XPASS, Test.XFAIL)[ok] 513be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 514be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ok = exitCode == 0 515be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar status = (Test.FAIL, Test.PASS)[ok] 516be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 517be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if ok: 518be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (status,'') 519be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 520be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return formatTestOutput(status, out, err, exitCode, script) 521be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 522ee504b8cd78f5d54e4ae6ed2cfff88a9e8226771Daniel Dunbardef executeShTest(test, litConfig, useExternalSh): 523be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if test.config.unsupported: 524be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.UNSUPPORTED, 'Test is unsupported') 525be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 526ee504b8cd78f5d54e4ae6ed2cfff88a9e8226771Daniel Dunbar res = parseIntegratedTestScript(test) 527be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if len(res) == 2: 528be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 529be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 53042543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar script, isXFail, tmpBase, execdir = res 531be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 532be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.noExecute: 533be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.PASS, '') 534be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 535be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Create the output directory if it does not already exist. 536be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar Util.mkdir_p(os.path.dirname(tmpBase)) 537be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 538be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if useExternalSh: 539be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeScript(test, litConfig, tmpBase, script, execdir) 540be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 541be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeScriptInternal(test, litConfig, tmpBase, script, execdir) 542be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if len(res) == 2: 543be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 544be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 545be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out,err,exitCode = res 54642543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar if isXFail: 547be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ok = exitCode != 0 548be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar status = (Test.XPASS, Test.XFAIL)[ok] 549be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 550be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ok = exitCode == 0 551be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar status = (Test.FAIL, Test.PASS)[ok] 552be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 553be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if ok: 554be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (status,'') 555be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 556be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return formatTestOutput(status, out, err, exitCode, script) 557