Skip to content

Commit 5606652

Browse files
sunshinecogitster
authored andcommitted
t/chainlint: add more chainlint.pl self-tests
During the development of chainlint.pl, numerous new self-tests were created to verify correct functioning beyond the checks already represented by the existing self-tests. The new checks fall into several categories: * behavior of the lexical analyzer for complex cases, such as line splicing, token pasting, entering and exiting string contexts inside and outside of test script bodies; for instance: test_expect_success 'title' ' x=$(echo "something" | sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\'' ' * behavior of the parser for all compound grammatical constructs, such as `if...fi`, `case...esac`, `while...done`, `{...}`, etc., and for other legal shell grammatical constructs not covered by existing chainlint.sed self-tests, as well as complex cases, such as: OUT=$( ((large_git 1>&3) | :) 3>&1 ) && * detection of problems, such as &&-chain breakage, from top-level to any depth since the existing self-tests do not cover any top-level context and only cover subshells one level deep due to limitations of chainlint.sed * address blind spots in chainlint.sed (such as not detecting a broken &&-chain on a one-line for-loop in a subshell[1]) which chainlint.pl correctly detects * real-world cases which tripped up chainlint.pl during its development [1]: https://lore.kernel.org/git/dce35a47012fecc6edc11c68e91dbb485c5bc36f.1661663880.git.gitgitgadget@gmail.com/ Signed-off-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ae0c55a commit 5606652

34 files changed

+336
-2
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
test_done ( ) {
2+
case "$test_failure" in
3+
0 )
4+
test_at_end_hook_
5+
6+
exit 0 ;;
7+
8+
* )
9+
if test $test_external_has_tap -eq 0
10+
then
11+
say_color error "# failed $test_failure among $msg"
12+
say "1..$test_count"
13+
fi
14+
15+
exit 1 ;;
16+
17+
esac
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# LINT: blank line before "esac"
2+
test_done () {
3+
case "$test_failure" in
4+
0)
5+
test_at_end_hook_
6+
7+
exit 0 ;;
8+
9+
*)
10+
if test $test_external_has_tap -eq 0
11+
then
12+
say_color error "# failed $test_failure among $msg"
13+
say "1..$test_count"
14+
fi
15+
16+
exit 1 ;;
17+
18+
esac
19+
}

t/chainlint/block.expect

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,15 @@
99
echo c
1010
} ?!AMP?!
1111
baz
12-
)
12+
) &&
13+
14+
{
15+
echo a ; ?!AMP?! echo b
16+
} &&
17+
{ echo a ; ?!AMP?! echo b ; } &&
18+
19+
{
20+
echo "${var}9" &&
21+
echo "done"
22+
} &&
23+
finis

t/chainlint/block.test

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,17 @@
1111
echo c
1212
}
1313
baz
14-
)
14+
) &&
15+
16+
# LINT: ";" not allowed in place of "&&"
17+
{
18+
echo a; echo b
19+
} &&
20+
{ echo a; echo b; } &&
21+
22+
# LINT: "}" inside string not mistaken as end of block
23+
{
24+
echo "${var}9" &&
25+
echo "done"
26+
} &&
27+
finis

t/chainlint/chained-block.expect

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
echo nobody home && {
2+
test the doohicky ?!AMP?!
3+
right now
4+
} &&
5+
6+
GIT_EXTERNAL_DIFF=echo git diff | {
7+
read path oldfile oldhex oldmode newfile newhex newmode &&
8+
test "z$oh" = "z$oldhex"
9+
}

t/chainlint/chained-block.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# LINT: start of block chained to preceding command
2+
echo nobody home && {
3+
test the doohicky
4+
right now
5+
} &&
6+
7+
# LINT: preceding command pipes to block on same line
8+
GIT_EXTERNAL_DIFF=echo git diff | {
9+
read path oldfile oldhex oldmode newfile newhex newmode &&
10+
test "z$oh" = "z$oldhex"
11+
}

t/chainlint/chained-subshell.expect

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
mkdir sub && (
2+
cd sub &&
3+
foo the bar ?!AMP?!
4+
nuff said
5+
) &&
6+
7+
cut "-d " -f actual | ( read s1 s2 s3 &&
8+
test -f $s1 ?!AMP?!
9+
test $(cat $s2) = tree2path1 &&
10+
test $(cat $s3) = tree3path1 )

t/chainlint/chained-subshell.test

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# LINT: start of subshell chained to preceding command
2+
mkdir sub && (
3+
cd sub &&
4+
foo the bar
5+
nuff said
6+
) &&
7+
8+
# LINT: preceding command pipes to subshell on same line
9+
cut "-d " -f actual | (read s1 s2 s3 &&
10+
test -f $s1
11+
test $(cat $s2) = tree2path1 &&
12+
# LINT: closing subshell ")" correctly detected on same line as "$(...)"
13+
test $(cat $s3) = tree3path1)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
OUT=$(( ( large_git 1 >& 3 ) | : ) 3 >& 1) &&
2+
test_match_signal 13 "$OUT"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# LINT: subshell nested in subshell nested in command substitution
2+
OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
3+
test_match_signal 13 "$OUT"

0 commit comments

Comments
 (0)