llvm.org GIT mirror llvm / 2263402
Revert r333584: [lit] Report line number for failed RUN command It breaks test-suite. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333592 91177308-0d34-0410-b5e6-96231b3b80d8 Joel E. Denny 1 year, 4 months ago
17 changed file(s) with 17 addition(s) and 190 deletion(s). Raw diff Collapse all Expand all
8484 Echo all commands to stdout, as they are being executed.
8585 This can be valuable for debugging test failures, as the last echoed command
8686 will be the one which has failed.
87 :program:`lit` normally inserts a no-op command (``:`` in the case of bash)
88 with argument ``'RUN: at line N'`` before each command pipeline, and this
89 option also causes those no-op commands to be echoed to stdout to help you
90 locate the source line of the failed command.
9187 This option implies ``--verbose``.
9288
9389 .. option:: -a, --show-all
3838 # Use temporary files to replace /dev/null on Windows.
3939 kAvoidDevNull = kIsWindows
4040 kDevNull = "/dev/null"
41
42 # A regex that matches %dbg(ARG), which lit inserts at the beginning of each
43 # run command pipeline such that ARG specifies the pipeline's source line
44 # number. lit later expands each %dbg(ARG) to a command that behaves as a null
45 # command in the target shell so that the line number is seen in lit's verbose
46 # mode.
47 #
48 # This regex captures ARG. ARG must not contain a right parenthesis, which
49 # terminates %dbg. ARG must not contain quotes, in which ARG might be enclosed
50 # during expansion.
51 kPdbgRegex = '%dbg\(([^)\'"]*)\)'
5241
5342 class ShellEnvironment(object):
5443
799788 results.append(cmdResult)
800789 return cmdResult.exitCode
801790
802 if cmd.commands[0].args[0] == ':':
803 if len(cmd.commands) != 1:
804 raise InternalShellError(cmd.commands[0], "Unsupported: ':' "
805 "cannot be part of a pipeline")
806 results.append(ShellCommandResult(cmd.commands[0], '', '', 0, False))
807 return 0;
808
809791 procs = []
810792 default_stdin = subprocess.PIPE
811793 stderrTempFiles = []
998980 return exitCode
999981
1000982 def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
1001 commands = applySubstitutions(commands, [(kPdbgRegex, ": '\\1'")])
1002983 cmds = []
1003984 for ln in commands:
1004985 try:
10691050 out += 'error: command reached timeout: %s\n' % (
10701051 str(result.timeoutReached),)
10711052
1072 return out, err, exitCode, timeoutInfo, commands
1053 return out, err, exitCode, timeoutInfo
10731054
10741055 def executeScript(test, litConfig, tmpBase, commands, cwd):
10751056 bashPath = litConfig.getBashPath()
10841065 mode += 'b' # Avoid CRLFs when writing bash scripts.
10851066 f = open(script, mode)
10861067 if isWin32CMDEXE:
1087 commands = applySubstitutions(commands, [(kPdbgRegex,
1088 "echo '\\1' > nul")])
1089 if litConfig.echo_all_commands:
1090 f.write('@echo on\n')
1091 else:
1092 f.write('@echo off\n')
1093 f.write('\n@if %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
1068 f.write('@echo off\n')
1069 f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
10941070 else:
1095 commands = applySubstitutions(commands, [(kPdbgRegex, ": '\\1'")])
10961071 if test.config.pipefail:
10971072 f.write('set -o pipefail;')
10981073 if litConfig.echo_all_commands:
11171092 out, err, exitCode = lit.util.executeCommand(command, cwd=cwd,
11181093 env=test.config.environment,
11191094 timeout=litConfig.maxIndividualTestTime)
1120 return (out, err, exitCode, None, commands)
1095 return (out, err, exitCode, None)
11211096 except lit.util.ExecuteCommandTimeoutException as e:
1122 return (e.out, e.err, e.exitCode, e.msg, commands)
1097 return (e.out, e.err, e.exitCode, e.msg)
11231098
11241099 def parseIntegratedTestScriptCommands(source_path, keywords):
11251100 """
12391214 ])
12401215 return substitutions
12411216
1242 def applySubstitutions(script, substitutions, escapeForWindows=False):
1217 def applySubstitutions(script, substitutions):
12431218 """Apply substitutions to the script. Allow full regular expression syntax.
12441219 Replace each matching occurrence of regular expression pattern a with
12451220 substitution b in line ln."""
12461221 def processLine(ln):
12471222 # Apply substitutions
12481223 for a,b in substitutions:
1249 if kIsWindows and escapeForWindows:
1224 if kIsWindows:
12501225 b = b.replace("\\","\\\\")
12511226 ln = re.sub(a, b, ln)
12521227
13251300 self.parser = parser
13261301
13271302 if kind == ParserKind.COMMAND:
1328 self.parser = lambda line_number, line, output: \
1329 self._handleCommand(line_number, line, output,
1330 self.keyword)
1303 self.parser = self._handleCommand
13311304 elif kind == ParserKind.LIST:
13321305 self.parser = self._handleList
13331306 elif kind == ParserKind.BOOLEAN_EXPR:
13581331 return (not line.strip() or output)
13591332
13601333 @staticmethod
1361 def _handleCommand(line_number, line, output, keyword):
1334 def _handleCommand(line_number, line, output):
13621335 """A helper for parsing COMMAND type keywords"""
13631336 # Trim trailing whitespace.
13641337 line = line.rstrip()
13771350 else:
13781351 if output is None:
13791352 output = []
1380 pdbg = "%dbg({keyword} at line {line_number})".format(
1381 keyword=keyword,
1382 line_number=line_number)
1383 assert re.match(kPdbgRegex + "$", pdbg), \
1384 "kPdbgRegex expected to match actual %dbg usage"
1385 line = "{pdbg} && {real_command}".format(
1386 pdbg=pdbg,
1387 real_command=line)
13881353 output.append(line)
13891354 return output
13901355
15231488 if isinstance(res, lit.Test.Result):
15241489 return res
15251490
1526 out,err,exitCode,timeoutInfo,script = res
1491 out,err,exitCode,timeoutInfo = res
15271492 if exitCode == 0:
15281493 status = Test.PASS
15291494 else:
15641529 substitutions = list(extra_substitutions)
15651530 substitutions += getDefaultSubstitutions(test, tmpDir, tmpBase,
15661531 normalize_slashes=useExternalSh)
1567 script = applySubstitutions(script, substitutions, True)
1532 script = applySubstitutions(script, substitutions)
15681533
15691534 # Re-run failed tests up to test_retry_attempts times.
15701535 attempts = 1
+0
-6
utils/lit/tests/Inputs/shtest-run-at-line/external-shell/basic.txt less more
None # These commands must run under both bash and windows cmd.exe (with GnuWin32
1 # tools).
2
3 # RUN: true
4 # RUN: false
5 # RUN: true
+0
-12
utils/lit/tests/Inputs/shtest-run-at-line/external-shell/line-continuation.txt less more
None # These commands must run under both bash and windows cmd.exe (with GnuWin32
1 # tools).
2
3 # RUN: echo 'foo bar' \
4 # RUN: | FileCheck %s
5 # RUN: echo \
6 # RUN: 'foo baz' \
7 # RUN: | FileCheck %s
8 # RUN: echo 'foo bar' \
9 # RUN: | FileCheck %s
10
11 # CHECK: foo bar
+0
-2
utils/lit/tests/Inputs/shtest-run-at-line/external-shell/lit.local.cfg less more
None import lit.formats
1 config.test_format = lit.formats.ShTest(execute_external=True)
+0
-3
utils/lit/tests/Inputs/shtest-run-at-line/internal-shell/basic.txt less more
None # RUN: true
1 # RUN: false
2 # RUN: true
+0
-11
utils/lit/tests/Inputs/shtest-run-at-line/internal-shell/line-continuation.txt less more
None # RUN: : first line continued \
1 # RUN: to second line
2 # RUN: echo 'foo bar' \
3 # RUN: | FileCheck %s
4 # RUN: echo \
5 # RUN: 'foo baz' \
6 # RUN: | FileCheck %s
7 # RUN: echo 'foo bar' \
8 # RUN: | FileCheck %s
9
10 # CHECK: foo bar
+0
-2
utils/lit/tests/Inputs/shtest-run-at-line/internal-shell/lit.local.cfg less more
None import lit.formats
1 config.test_format = lit.formats.ShTest(execute_external=False)
+0
-2
utils/lit/tests/Inputs/shtest-run-at-line/lit.cfg less more
None config.name = 'shtest-run-at-line'
1 config.suffixes = ['.txt']
+0
-3
utils/lit/tests/Inputs/shtest-shell/colon-error.txt less more
None # Check error on an unsupported ":". (cannot be part of a pipeline)
1 #
2 # RUN: : | echo "hello"
7070 if directory:
7171 path = os.path.pathsep.join((directory, path))
7272 config.environment['PATH'] = path
73
74 # These substitutions are needed only in tests where the external shell is used
75 # and could be either bash or windows cmd.exe. Substitutions are expected to
76 # be expanded in double quotes.
77 isWin32CMDEXE = lit_config.isWindows and not lit_config.getBashPath()
78 if isWin32CMDEXE:
79 config.substitutions.append(('%{pdbg0}', "echo '"))
80 config.substitutions.append(('%{pdbg1}', "' > nul"))
81 else:
82 config.substitutions.append(('%{pdbg0}', ": '"))
83 config.substitutions.append(('%{pdbg1}', "'"))
77 #
88 # END.
99
10 # CHECK: Failing Tests (27)
10 # CHECK: Failing Tests (26)
1111 # CHECK: Failing Tests (1)
1212 # CHECK: Failing Tests (2)
1313 # CHECK: error: Setting --max-failures to 0 does not have any effect.
3838 #
3939 # CHECK: Command Output (stdout):
4040 # CHECK-NEXT: --
41 # CHECK-NEXT: $ ":" "RUN: at line 1"
4241 # CHECK-NEXT: $ "printf"
4342 # CHECK-NEXT: # command output:
4443 # CHECK-NEXT: line 1: failed test output on stdout
1515 #
1616 # CHECK: Command Output
1717 # CHECK-NEXT: --
18 # CHECK-NEXT: $ ":" "RUN: at line 1"
1918 # CHECK-NEXT: $ "true"
20 # CHECK-NEXT: $ ":" "RUN: at line 2"
2119 # CHECK-NEXT: $ "echo" "hi"
2220 # CHECK-NEXT: # command output:
2321 # CHECK-NEXT: hi
2422 #
25 # CHECK: $ ":" "RUN: at line 3"
26 # CHECK-NEXT: $ "wc" "missing-file"
23 # CHECK: $ "wc" "missing-file"
2724 # CHECK-NEXT: # redirected output from '{{.*(/|\\\\)}}basic.txt.tmp.out':
2825 # CHECK-NEXT: missing-file{{.*}} No such file or directory
2926 # CHECK: note: command had no output on stdout or stderr
+0
-70
utils/lit/tests/shtest-run-at-line.py less more
None # Check that -vv makes the line number of the failing RUN command clear.
1 # (-v is actually sufficient in the case of the internal shell.)
2 #
3 # RUN: not %{lit} -j 1 -vv %{inputs}/shtest-run-at-line > %t.out
4 # RUN: FileCheck --input-file %t.out -Dpdbg0="%{pdbg0}" -Dpdbg1="%{pdbg1}" %s
5 #
6 # END.
7
8
9 # CHECK: Testing: 4 tests
10
11
12 # In the case of the external shell, we check for only RUN lines in stderr in
13 # case some shell implementations format "set -x" output differently.
14
15 # CHECK-LABEL: FAIL: shtest-run-at-line :: external-shell/basic.txt
16
17 # CHECK: Script:
18 # CHECK: [[pdbg0]]RUN: at line 4[[pdbg1]] && true
19 # CHECK-NEXT: [[pdbg0]]RUN: at line 5[[pdbg1]] && false
20 # CHECK-NEXT: [[pdbg0]]RUN: at line 6[[pdbg1]] && true
21
22 # CHECK: RUN: at line 4
23 # CHECK: RUN: at line 5
24 # CHECK-NOT: RUN
25
26 # CHECK-LABEL: FAIL: shtest-run-at-line :: external-shell/line-continuation.txt
27
28 # CHECK: Script:
29 # CHECK: [[pdbg0]]RUN: at line 4[[pdbg1]] && echo 'foo bar' | FileCheck
30 # CHECK-NEXT: [[pdbg0]]RUN: at line 6[[pdbg1]] && echo 'foo baz' | FileCheck
31 # CHECK-NEXT: [[pdbg0]]RUN: at line 9[[pdbg1]] && echo 'foo bar' | FileCheck
32
33 # CHECK: RUN: at line 4
34 # CHECK: RUN: at line 6
35 # CHECK-NOT: RUN
36
37
38 # CHECK-LABEL: FAIL: shtest-run-at-line :: internal-shell/basic.txt
39
40 # CHECK: Script:
41 # CHECK: : 'RUN: at line 1' && true
42 # CHECK-NEXT: : 'RUN: at line 2' && false
43 # CHECK-NEXT: : 'RUN: at line 3' && true
44
45 # CHECK: Command Output (stdout)
46 # CHECK: $ ":" "RUN: at line 1"
47 # CHECK-NEXT: $ "true"
48 # CHECK-NEXT: $ ":" "RUN: at line 2"
49 # CHECK-NEXT: $ "false"
50 # CHECK-NOT: RUN
51
52 # CHECK-LABEL: FAIL: shtest-run-at-line :: internal-shell/line-continuation.txt
53
54 # CHECK: Script:
55 # CHECK: : 'RUN: at line 1' && : first line continued to second line
56 # CHECK-NEXT: : 'RUN: at line 3' && echo 'foo bar' | FileCheck
57 # CHECK-NEXT: : 'RUN: at line 5' && echo 'foo baz' | FileCheck
58 # CHECK-NEXT: : 'RUN: at line 8' && echo 'foo bar' | FileCheck
59
60 # CHECK: Command Output (stdout)
61 # CHECK: $ ":" "RUN: at line 1"
62 # CHECK-NEXT: $ ":" "first" "line" "continued" "to" "second" "line"
63 # CHECK-NEXT: $ ":" "RUN: at line 3"
64 # CHECK-NEXT: $ "echo" "foo bar"
65 # CHECK-NEXT: $ "FileCheck" "{{.*}}"
66 # CHECK-NEXT: $ ":" "RUN: at line 5"
67 # CHECK-NEXT: $ "echo" "foo baz"
68 # CHECK-NEXT: $ "FileCheck" "{{.*}}"
69 # CHECK-NOT: RUN
2525 # CHECK: error: command failed with exit status: 1
2626 # CHECK: ***
2727
28 # CHECK: FAIL: shtest-shell :: colon-error.txt
29 # CHECK: *** TEST 'shtest-shell :: colon-error.txt' FAILED ***
30 # CHECK: $ ":"
31 # CHECK: # command stderr:
32 # CHECK: Unsupported: ':' cannot be part of a pipeline
33 # CHECK: error: command failed with exit status: 127
34 # CHECK: ***
35
3628 # CHECK: FAIL: shtest-shell :: diff-error-0.txt
3729 # CHECK: *** TEST 'shtest-shell :: diff-error-0.txt' FAILED ***
3830 # CHECK: $ "diff" "diff-error-0.txt" "diff-error-0.txt"
160152 #
161153 # CHECK: FAIL: shtest-shell :: error-1.txt
162154 # CHECK: *** TEST 'shtest-shell :: error-1.txt' FAILED ***
163 # CHECK: shell parser error on: ': \'RUN: at line 3\' && echo "missing quote'
155 # CHECK: shell parser error on: 'echo "missing quote'
164156 # CHECK: ***
165157
166158 # CHECK: FAIL: shtest-shell :: error-2.txt
226218 # CHECK: PASS: shtest-shell :: sequencing-0.txt
227219 # CHECK: XFAIL: shtest-shell :: sequencing-1.txt
228220 # CHECK: PASS: shtest-shell :: valid-shell.txt
229 # CHECK: Failing Tests (27)
221 # CHECK: Failing Tests (26)
9898 cmd_parser = self.get_parser(parsers, 'MY_RUN:')
9999 value = cmd_parser.getValue()
100100 self.assertEqual(len(value), 2) # there are only two run lines
101 self.assertEqual(value[0].strip(), "%dbg(MY_RUN: at line 4) && baz")
102 self.assertEqual(value[1].strip(), "%dbg(MY_RUN: at line 7) && foo bar")
101 self.assertEqual(value[0].strip(), 'baz')
102 self.assertEqual(value[1].strip(), 'foo bar')
103103
104104 def test_custom(self):
105105 parsers = self.make_parsers()