Skip to content

Commit 79b00ce

Browse files
sunshinecogitster
authored andcommitted
t/chainlint: add chainlint "loop" and "conditional" test cases
The --chain-lint option uses heuristics and knowledge of shell syntax to detect broken &&-chains in subshells by pure textual inspection. The heuristics handle a range of stylistic variations in existing tests (evolved over the years), however, they are still best-guesses. As such, it is possible for future changes to accidentally break assumptions upon which the heuristics are based. Protect against this possibility by adding tests which check the linter itself for correctness. In addition to protecting against regressions, these tests help document (for humans) expected behavior, which is important since the linter's implementation language ('sed') does not necessarily lend itself to easy comprehension. Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 117724d commit 79b00ce

File tree

10 files changed

+200
-0
lines changed

10 files changed

+200
-0
lines changed

t/chainlint/case.expect

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(
2+
case "$x" in
3+
x) foo ;;
4+
*) bar ;;
5+
esac &&
6+
foobar
7+
>) &&
8+
(
9+
case "$x" in
10+
x) foo ;;
11+
*) bar ;;
12+
?!AMP?! esac
13+
foobar
14+
>) &&
15+
(
16+
case "$x" in 1) true;; esac &&
17+
?!AMP?! case "$y" in 2) false;; esac
18+
foobar
19+
>)

t/chainlint/case.test

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
(
2+
# LINT: "...)" arms in 'case' not misinterpreted as subshell-closing ")"
3+
case "$x" in
4+
x) foo ;;
5+
*) bar ;;
6+
esac &&
7+
foobar
8+
) &&
9+
(
10+
# LINT: missing "&&" on 'esac'
11+
case "$x" in
12+
x) foo ;;
13+
*) bar ;;
14+
esac
15+
foobar
16+
) &&
17+
(
18+
# LINT: "...)" arm in one-liner 'case' not misinterpreted as closing ")"
19+
case "$x" in 1) true;; esac &&
20+
# LINT: same but missing "&&"
21+
case "$y" in 2) false;; esac
22+
foobar
23+
)

t/chainlint/exit-loop.expect

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(
2+
for i in a b c
3+
do
4+
foo || exit 1
5+
bar &&
6+
baz
7+
done
8+
>) &&
9+
(
10+
while true
11+
do
12+
foo || exit 1
13+
bar &&
14+
baz
15+
done
16+
>) &&
17+
(
18+
i=0 &&
19+
while test $i -lt 10
20+
do
21+
echo $i || exit
22+
i=$(($i + 1))
23+
done
24+
>)

t/chainlint/exit-loop.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
(
2+
for i in a b c
3+
do
4+
# LINT: "|| exit {n}" valid for-loop escape in subshell; no "&&" needed
5+
foo || exit 1
6+
bar &&
7+
baz
8+
done
9+
) &&
10+
(
11+
while true
12+
do
13+
# LINT: "|| exit {n}" valid while-loop escape in subshell; no "&&" needed
14+
foo || exit 1
15+
bar &&
16+
baz
17+
done
18+
) &&
19+
(
20+
i=0 &&
21+
while test $i -lt 10
22+
do
23+
# LINT: "|| exit" (sans exit code) valid escape in subshell; no "&&" needed
24+
echo $i || exit
25+
i=$(($i + 1))
26+
done
27+
)

t/chainlint/for-loop.expect

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(
2+
for i in a b c
3+
do
4+
?!AMP?! echo $i
5+
cat
6+
?!AMP?! done
7+
for i in a b c; do
8+
echo $i &&
9+
cat $i
10+
done
11+
>)

t/chainlint/for-loop.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(
2+
# LINT: 'for', 'do', 'done' do not need "&&"
3+
for i in a b c
4+
do
5+
# LINT: missing "&&" on 'echo'
6+
echo $i
7+
# LINT: last statement of while does not need "&&"
8+
cat <<-\EOF
9+
bar
10+
EOF
11+
# LINT: missing "&&" on 'done'
12+
done
13+
14+
# LINT: 'do' on same line as 'for'
15+
for i in a b c; do
16+
echo $i &&
17+
cat $i
18+
done
19+
)

t/chainlint/if-then-else.expect

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(
2+
if test -n ""
3+
then
4+
?!AMP?! echo very
5+
echo empty
6+
elif test -z ""
7+
echo foo
8+
else
9+
echo foo &&
10+
cat
11+
?!AMP?! fi
12+
echo poodle
13+
>) &&
14+
(
15+
if test -n ""; then
16+
echo very &&
17+
?!AMP?! echo empty
18+
if
19+
>)

t/chainlint/if-then-else.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
(
2+
# LINT: 'if', 'then', 'elif', 'else', 'fi' do not need "&&"
3+
if test -n ""
4+
then
5+
# LINT: missing "&&" on 'echo'
6+
echo very
7+
# LINT: last statement before 'elif' does not need "&&"
8+
echo empty
9+
elif test -z ""
10+
# LINT: last statement before 'else' does not need "&&"
11+
echo foo
12+
else
13+
echo foo &&
14+
# LINT: last statement before 'fi' does not need "&&"
15+
cat <<-\EOF
16+
bar
17+
EOF
18+
# LINT: missing "&&" on 'fi'
19+
fi
20+
echo poodle
21+
) &&
22+
(
23+
# LINT: 'then' on same line as 'if'
24+
if test -n ""; then
25+
echo very &&
26+
echo empty
27+
if
28+
)

t/chainlint/while-loop.expect

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(
2+
while true
3+
do
4+
?!AMP?! echo foo
5+
cat
6+
?!AMP?! done
7+
while true; do
8+
echo foo &&
9+
cat bar
10+
done
11+
>)

t/chainlint/while-loop.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
(
2+
# LINT: 'while, 'do', 'done' do not need "&&"
3+
while true
4+
do
5+
# LINT: missing "&&" on 'echo'
6+
echo foo
7+
# LINT: last statement of while does not need "&&"
8+
cat <<-\EOF
9+
bar
10+
EOF
11+
# LINT: missing "&&" on 'done'
12+
done
13+
14+
# LINT: 'do' on same line as 'while'
15+
while true; do
16+
echo foo &&
17+
cat bar
18+
done
19+
)

0 commit comments

Comments
 (0)