diff options
author | Vincent Ambo <Vincent Ambo> | 2020-01-11T23·36+0000 |
---|---|---|
committer | Vincent Ambo <Vincent Ambo> | 2020-01-11T23·36+0000 |
commit | 1b593e1ea4d2af0f6444d9a7788d5d99abd6fde5 (patch) | |
tree | e3accb9beed5c4c1b5a05c99db71ab2841f0ed04 /t/chainlint |
Squashed 'third_party/git/' content from commit cb71568594
git-subtree-dir: third_party/git git-subtree-split: cb715685942260375e1eb8153b0768a376e4ece7
Diffstat (limited to 't/chainlint')
82 files changed, 1108 insertions, 0 deletions
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect new file mode 100644 index 000000000000..09457d319661 --- /dev/null +++ b/t/chainlint/arithmetic-expansion.expect @@ -0,0 +1,9 @@ +( + foo && + bar=$((42 + 1)) && + baz +>) && +( +?!AMP?! bar=$((42 + 1)) + baz +>) diff --git a/t/chainlint/arithmetic-expansion.test b/t/chainlint/arithmetic-expansion.test new file mode 100644 index 000000000000..16206960d8b0 --- /dev/null +++ b/t/chainlint/arithmetic-expansion.test @@ -0,0 +1,11 @@ +( + foo && +# LINT: closing ")" of $((...)) not misinterpreted as subshell-closing ")" + bar=$((42 + 1)) && + baz +) && +( +# LINT: missing "&&" on $((...)) + bar=$((42 + 1)) + baz +) diff --git a/t/chainlint/bash-array.expect b/t/chainlint/bash-array.expect new file mode 100644 index 000000000000..c4a830d1c1d6 --- /dev/null +++ b/t/chainlint/bash-array.expect @@ -0,0 +1,10 @@ +( + foo && + bar=(gumbo stumbo wumbo) && + baz +>) && +( + foo && + bar=${#bar[@]} && + baz +>) diff --git a/t/chainlint/bash-array.test b/t/chainlint/bash-array.test new file mode 100644 index 000000000000..92bbb777b82a --- /dev/null +++ b/t/chainlint/bash-array.test @@ -0,0 +1,12 @@ +( + foo && +# LINT: ")" in Bash array assignment not misinterpreted as subshell-closing ")" + bar=(gumbo stumbo wumbo) && + baz +) && +( + foo && +# LINT: Bash array length operator not misinterpreted as comment + bar=${#bar[@]} && + baz +) diff --git a/t/chainlint/blank-line.expect b/t/chainlint/blank-line.expect new file mode 100644 index 000000000000..3be939ed388c --- /dev/null +++ b/t/chainlint/blank-line.expect @@ -0,0 +1,4 @@ +( + nothing && + something +>) diff --git a/t/chainlint/blank-line.test b/t/chainlint/blank-line.test new file mode 100644 index 000000000000..f6dd14302b2b --- /dev/null +++ b/t/chainlint/blank-line.test @@ -0,0 +1,10 @@ +( + + nothing && + + something +# LINT: swallow blank lines since final _statement_ before subshell end is +# LINT: significant to "&&"-check, not final _line_ (which might be blank) + + +) diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect new file mode 100644 index 000000000000..fed7e89ae8ff --- /dev/null +++ b/t/chainlint/block.expect @@ -0,0 +1,12 @@ +( + foo && + { + echo a + echo b + } && + bar && + { + echo c +?!AMP?! } + baz +>) diff --git a/t/chainlint/block.test b/t/chainlint/block.test new file mode 100644 index 000000000000..d859151af1d9 --- /dev/null +++ b/t/chainlint/block.test @@ -0,0 +1,15 @@ +( +# LINT: missing "&&" in block not currently detected (for consistency with +# LINT: --chain-lint at top level and to provide escape hatch if needed) + foo && + { + echo a + echo b + } && + bar && +# LINT: missing "&&" at closing "}" + { + echo c + } + baz +) diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect new file mode 100644 index 000000000000..55b0f42a534d --- /dev/null +++ b/t/chainlint/broken-chain.expect @@ -0,0 +1,6 @@ +( + foo && +?!AMP?! bar + baz && + wop +>) diff --git a/t/chainlint/broken-chain.test b/t/chainlint/broken-chain.test new file mode 100644 index 000000000000..3cc67b65d0c9 --- /dev/null +++ b/t/chainlint/broken-chain.test @@ -0,0 +1,8 @@ +( + foo && +# LINT: missing "&&" from 'bar' + bar + baz && +# LINT: final statement before closing ")" legitimately lacks "&&" + wop +) diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect new file mode 100644 index 000000000000..41f121fbbf9c --- /dev/null +++ b/t/chainlint/case.expect @@ -0,0 +1,19 @@ +( + case "$x" in + x) foo ;; + *) bar ;; + esac && + foobar +>) && +( + case "$x" in + x) foo ;; + *) bar ;; +?!AMP?! esac + foobar +>) && +( + case "$x" in 1) true;; esac && +?!AMP?! case "$y" in 2) false;; esac + foobar +>) diff --git a/t/chainlint/case.test b/t/chainlint/case.test new file mode 100644 index 000000000000..5ef6ff7db5ea --- /dev/null +++ b/t/chainlint/case.test @@ -0,0 +1,23 @@ +( +# LINT: "...)" arms in 'case' not misinterpreted as subshell-closing ")" + case "$x" in + x) foo ;; + *) bar ;; + esac && + foobar +) && +( +# LINT: missing "&&" on 'esac' + case "$x" in + x) foo ;; + *) bar ;; + esac + foobar +) && +( +# LINT: "...)" arm in one-liner 'case' not misinterpreted as closing ")" + case "$x" in 1) true;; esac && +# LINT: same but missing "&&" + case "$y" in 2) false;; esac + foobar +) diff --git a/t/chainlint/close-nested-and-parent-together.expect b/t/chainlint/close-nested-and-parent-together.expect new file mode 100644 index 000000000000..2a910f9d6660 --- /dev/null +++ b/t/chainlint/close-nested-and-parent-together.expect @@ -0,0 +1,4 @@ +( +cd foo && + (bar && +>>> baz)) diff --git a/t/chainlint/close-nested-and-parent-together.test b/t/chainlint/close-nested-and-parent-together.test new file mode 100644 index 000000000000..72d482f76dd2 --- /dev/null +++ b/t/chainlint/close-nested-and-parent-together.test @@ -0,0 +1,3 @@ +(cd foo && + (bar && + baz)) diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect new file mode 100644 index 000000000000..184688718a9c --- /dev/null +++ b/t/chainlint/close-subshell.expect @@ -0,0 +1,25 @@ +( + foo +>) && +( + bar +>) >out && +( + baz +>) 2>err && +( + boo +>) <input && +( + bip +>) | wuzzle && +( + bop +>) | fazz fozz && +( + bup +>) | +fuzzle && +( + yop +>) diff --git a/t/chainlint/close-subshell.test b/t/chainlint/close-subshell.test new file mode 100644 index 000000000000..508ca447fd6c --- /dev/null +++ b/t/chainlint/close-subshell.test @@ -0,0 +1,27 @@ +# LINT: closing ")" with various decorations ("&&", ">", "|", etc.) +( + foo +) && +( + bar +) >out && +( + baz +) 2>err && +( + boo +) <input && +( + bip +) | wuzzle && +( + bop +) | fazz \ + fozz && +( + bup +) | +fuzzle && +( + yop +) diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect new file mode 100644 index 000000000000..ad4118e537e4 --- /dev/null +++ b/t/chainlint/command-substitution.expect @@ -0,0 +1,9 @@ +( + foo && + bar=$(gobble) && + baz +>) && +( +?!AMP?! bar=$(gobble blocks) + baz +>) diff --git a/t/chainlint/command-substitution.test b/t/chainlint/command-substitution.test new file mode 100644 index 000000000000..3bbb002a4c74 --- /dev/null +++ b/t/chainlint/command-substitution.test @@ -0,0 +1,11 @@ +( + foo && +# LINT: closing ")" of $(...) not misinterpreted as subshell-closing ")" + bar=$(gobble) && + baz +) && +( +# LINT: missing "&&" on $(...) + bar=$(gobble blocks) + baz +) diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect new file mode 100644 index 000000000000..3be939ed388c --- /dev/null +++ b/t/chainlint/comment.expect @@ -0,0 +1,4 @@ +( + nothing && + something +>) diff --git a/t/chainlint/comment.test b/t/chainlint/comment.test new file mode 100644 index 000000000000..113c0c466f17 --- /dev/null +++ b/t/chainlint/comment.test @@ -0,0 +1,11 @@ +( +# LINT: swallow comment lines + # comment 1 + nothing && + # comment 2 + something +# LINT: swallow comment lines since final _statement_ before subshell end is +# LINT: significant to "&&"-check, not final _line_ (which might be comment) + # comment 3 + # comment 4 +) diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect new file mode 100644 index 000000000000..9674b88cf252 --- /dev/null +++ b/t/chainlint/complex-if-in-cuddled-loop.expect @@ -0,0 +1,10 @@ +( +for i in a b c; do + if test "$(echo $(waffle bat))" = "eleventeen" && + test "$x" = "$y"; then + : + else + echo >file + fi +> done) && +test ! -f file diff --git a/t/chainlint/complex-if-in-cuddled-loop.test b/t/chainlint/complex-if-in-cuddled-loop.test new file mode 100644 index 000000000000..571bbd85cdfc --- /dev/null +++ b/t/chainlint/complex-if-in-cuddled-loop.test @@ -0,0 +1,11 @@ +# LINT: 'for' loop cuddled with "(" and ")" and nested 'if' with complex +# LINT: multi-line condition; indented with spaces, not tabs +(for i in a b c; do + if test "$(echo $(waffle bat))" = "eleventeen" && + test "$x" = "$y"; then + : + else + echo >file + fi + done) && +test ! -f file diff --git a/t/chainlint/cuddled-if-then-else.expect b/t/chainlint/cuddled-if-then-else.expect new file mode 100644 index 000000000000..ab2a026fbc2f --- /dev/null +++ b/t/chainlint/cuddled-if-then-else.expect @@ -0,0 +1,7 @@ +( +if test -z ""; then + echo empty + else + echo bizzy +> fi) && +echo foobar diff --git a/t/chainlint/cuddled-if-then-else.test b/t/chainlint/cuddled-if-then-else.test new file mode 100644 index 000000000000..eed774a9d643 --- /dev/null +++ b/t/chainlint/cuddled-if-then-else.test @@ -0,0 +1,7 @@ +# LINT: 'if' cuddled with "(" and ")"; indented with spaces, not tabs +(if test -z ""; then + echo empty + else + echo bizzy + fi) && +echo foobar diff --git a/t/chainlint/cuddled-loop.expect b/t/chainlint/cuddled-loop.expect new file mode 100644 index 000000000000..8c0260d7f1d9 --- /dev/null +++ b/t/chainlint/cuddled-loop.expect @@ -0,0 +1,5 @@ +( + while read x + do foobar bop || exit 1 +> done <file ) && +outside subshell diff --git a/t/chainlint/cuddled-loop.test b/t/chainlint/cuddled-loop.test new file mode 100644 index 000000000000..a841d781f04f --- /dev/null +++ b/t/chainlint/cuddled-loop.test @@ -0,0 +1,7 @@ +# LINT: 'while' loop cuddled with "(" and ")", with embedded (allowed) +# LINT: "|| exit {n}" to exit loop early, and using redirection "<" to feed +# LINT: loop; indented with spaces, not tabs +( while read x + do foobar bop || exit 1 + done <file ) && +outside subshell diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect new file mode 100644 index 000000000000..b506d4622197 --- /dev/null +++ b/t/chainlint/cuddled.expect @@ -0,0 +1,21 @@ +( +cd foo && + bar +>) && + +( +?!AMP?!cd foo + bar +>) && + +( + cd foo && +> bar) && + +( +cd foo && +> bar) && + +( +?!AMP?!cd foo +> bar) diff --git a/t/chainlint/cuddled.test b/t/chainlint/cuddled.test new file mode 100644 index 000000000000..0499fa418059 --- /dev/null +++ b/t/chainlint/cuddled.test @@ -0,0 +1,23 @@ +# LINT: first subshell statement cuddled with opening "("; for implementation +# LINT: simplicity, "(..." is split into two lines, "(" and "..." +(cd foo && + bar +) && + +# LINT: same with missing "&&" +(cd foo + bar +) && + +# LINT: closing ")" cuddled with final subshell statement +( + cd foo && + bar) && + +# LINT: "(" and ")" cuddled with first and final subshell statements +(cd foo && + bar) && + +# LINT: same with missing "&&" +(cd foo + bar) diff --git a/t/chainlint/exit-loop.expect b/t/chainlint/exit-loop.expect new file mode 100644 index 000000000000..84d8bdebc026 --- /dev/null +++ b/t/chainlint/exit-loop.expect @@ -0,0 +1,24 @@ +( + for i in a b c + do + foo || exit 1 + bar && + baz + done +>) && +( + while true + do + foo || exit 1 + bar && + baz + done +>) && +( + i=0 && + while test $i -lt 10 + do + echo $i || exit + i=$(($i + 1)) + done +>) diff --git a/t/chainlint/exit-loop.test b/t/chainlint/exit-loop.test new file mode 100644 index 000000000000..2f038207e194 --- /dev/null +++ b/t/chainlint/exit-loop.test @@ -0,0 +1,27 @@ +( + for i in a b c + do +# LINT: "|| exit {n}" valid for-loop escape in subshell; no "&&" needed + foo || exit 1 + bar && + baz + done +) && +( + while true + do +# LINT: "|| exit {n}" valid while-loop escape in subshell; no "&&" needed + foo || exit 1 + bar && + baz + done +) && +( + i=0 && + while test $i -lt 10 + do +# LINT: "|| exit" (sans exit code) valid escape in subshell; no "&&" needed + echo $i || exit + i=$(($i + 1)) + done +) diff --git a/t/chainlint/exit-subshell.expect b/t/chainlint/exit-subshell.expect new file mode 100644 index 000000000000..bf78454f74c8 --- /dev/null +++ b/t/chainlint/exit-subshell.expect @@ -0,0 +1,5 @@ +( + foo || exit 1 + bar && + baz +>) diff --git a/t/chainlint/exit-subshell.test b/t/chainlint/exit-subshell.test new file mode 100644 index 000000000000..4e6ab69b8867 --- /dev/null +++ b/t/chainlint/exit-subshell.test @@ -0,0 +1,6 @@ +( +# LINT: "|| exit {n}" valid subshell escape without hurting &&-chain + foo || exit 1 + bar && + baz +) diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect new file mode 100644 index 000000000000..c33cf56ee73a --- /dev/null +++ b/t/chainlint/for-loop.expect @@ -0,0 +1,11 @@ +( + for i in a b c + do +?!AMP?! echo $i + cat +?!AMP?! done + for i in a b c; do + echo $i && + cat $i + done +>) diff --git a/t/chainlint/for-loop.test b/t/chainlint/for-loop.test new file mode 100644 index 000000000000..7db76262bc2e --- /dev/null +++ b/t/chainlint/for-loop.test @@ -0,0 +1,19 @@ +( +# LINT: 'for', 'do', 'done' do not need "&&" + for i in a b c + do +# LINT: missing "&&" on 'echo' + echo $i +# LINT: last statement of while does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on 'done' + done + +# LINT: 'do' on same line as 'for' + for i in a b c; do + echo $i && + cat $i + done +) diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect new file mode 100644 index 000000000000..f011e335e5f1 --- /dev/null +++ b/t/chainlint/here-doc-close-subshell.expect @@ -0,0 +1,2 @@ +( +> cat) diff --git a/t/chainlint/here-doc-close-subshell.test b/t/chainlint/here-doc-close-subshell.test new file mode 100644 index 000000000000..b857ff546765 --- /dev/null +++ b/t/chainlint/here-doc-close-subshell.test @@ -0,0 +1,5 @@ +( +# LINT: line contains here-doc and closes nested subshell + cat <<-\INPUT) + fizz + INPUT diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect new file mode 100644 index 000000000000..e5fb752d2fc2 --- /dev/null +++ b/t/chainlint/here-doc-multi-line-command-subst.expect @@ -0,0 +1,5 @@ +( + x=$(bobble && +?!AMP?!>> wiffle) + echo $x +>) diff --git a/t/chainlint/here-doc-multi-line-command-subst.test b/t/chainlint/here-doc-multi-line-command-subst.test new file mode 100644 index 000000000000..899bc5de8bce --- /dev/null +++ b/t/chainlint/here-doc-multi-line-command-subst.test @@ -0,0 +1,9 @@ +( +# LINT: line contains here-doc and opens multi-line $(...) + x=$(bobble <<-\END && + fossil + vegetable + END + wiffle) + echo $x +) diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect new file mode 100644 index 000000000000..32038a070c2a --- /dev/null +++ b/t/chainlint/here-doc-multi-line-string.expect @@ -0,0 +1,4 @@ +( +?!AMP?! cat && echo "multi-line string" + bap +>) diff --git a/t/chainlint/here-doc-multi-line-string.test b/t/chainlint/here-doc-multi-line-string.test new file mode 100644 index 000000000000..a53edbcc8d89 --- /dev/null +++ b/t/chainlint/here-doc-multi-line-string.test @@ -0,0 +1,8 @@ +( +# LINT: line contains here-doc and opens multi-line string + cat <<-\TXT && echo "multi-line + string" + fizzle + TXT + bap +) diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect new file mode 100644 index 000000000000..534b065e38ba --- /dev/null +++ b/t/chainlint/here-doc.expect @@ -0,0 +1,9 @@ +boodle wobba gorgo snoot wafta snurb && + +cat >foo && + +cat >bar && + +cat >boo && + +horticulture diff --git a/t/chainlint/here-doc.test b/t/chainlint/here-doc.test new file mode 100644 index 000000000000..ad4ce8afd9b5 --- /dev/null +++ b/t/chainlint/here-doc.test @@ -0,0 +1,37 @@ +# LINT: stitch together incomplete \-ending lines +# LINT: swallow here-doc to avoid false positives in content +boodle wobba \ + gorgo snoot \ + wafta snurb <<EOF && +quoth the raven, +nevermore... +EOF + +# LINT: swallow here-doc with arbitrary tag +cat <<-Arbitrary_Tag_42 >foo && +snoz +boz +woz +Arbitrary_Tag_42 + +# LINT: swallow 'quoted' here-doc +cat <<'FUMP' >bar && +snoz +boz +woz +FUMP + +# LINT: swallow "quoted" here-doc +cat <<"zump" >boo && +snoz +boz +woz +zump + +# LINT: swallow here-doc (EOF is last line of test) +horticulture <<\EOF +gomez +morticia +wednesday +pugsly +EOF diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect new file mode 100644 index 000000000000..03d3ceb22d89 --- /dev/null +++ b/t/chainlint/if-in-loop.expect @@ -0,0 +1,12 @@ +( + for i in a b c + do + if false + then +?!AMP?! echo "err" + exit 1 +?!AMP?! fi + foo +?!AMP?! done + bar +>) diff --git a/t/chainlint/if-in-loop.test b/t/chainlint/if-in-loop.test new file mode 100644 index 000000000000..daf22da16476 --- /dev/null +++ b/t/chainlint/if-in-loop.test @@ -0,0 +1,15 @@ +( + for i in a b c + do + if false + then +# LINT: missing "&&" on 'echo' + echo "err" + exit 1 +# LINT: missing "&&" on 'fi' + fi + foo +# LINT: missing "&&" on 'done' + done + bar +) diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect new file mode 100644 index 000000000000..5953c7bfbc2e --- /dev/null +++ b/t/chainlint/if-then-else.expect @@ -0,0 +1,19 @@ +( + if test -n "" + then +?!AMP?! echo very + echo empty + elif test -z "" + echo foo + else + echo foo && + cat +?!AMP?! fi + echo poodle +>) && +( + if test -n ""; then + echo very && +?!AMP?! echo empty + if +>) diff --git a/t/chainlint/if-then-else.test b/t/chainlint/if-then-else.test new file mode 100644 index 000000000000..9bd8e9a4c68c --- /dev/null +++ b/t/chainlint/if-then-else.test @@ -0,0 +1,28 @@ +( +# LINT: 'if', 'then', 'elif', 'else', 'fi' do not need "&&" + if test -n "" + then +# LINT: missing "&&" on 'echo' + echo very +# LINT: last statement before 'elif' does not need "&&" + echo empty + elif test -z "" +# LINT: last statement before 'else' does not need "&&" + echo foo + else + echo foo && +# LINT: last statement before 'fi' does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on 'fi' + fi + echo poodle +) && +( +# LINT: 'then' on same line as 'if' + if test -n ""; then + echo very && + echo empty + if +) diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect new file mode 100644 index 000000000000..2f3ebabdc286 --- /dev/null +++ b/t/chainlint/incomplete-line.expect @@ -0,0 +1,4 @@ +line 1 line 2 line 3 line 4 && +( + line 5 line 6 line 7 line 8 +>) diff --git a/t/chainlint/incomplete-line.test b/t/chainlint/incomplete-line.test new file mode 100644 index 000000000000..d8566580839b --- /dev/null +++ b/t/chainlint/incomplete-line.test @@ -0,0 +1,12 @@ +# LINT: stitch together all incomplete \-ending lines +line 1 \ +line 2 \ +line 3 \ +line 4 && +( +# LINT: stitch together all incomplete \-ending lines (subshell) + line 5 \ + line 6 \ + line 7 \ + line 8 +) diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect new file mode 100644 index 000000000000..fc9f250ac48e --- /dev/null +++ b/t/chainlint/inline-comment.expect @@ -0,0 +1,9 @@ +( + foobar && +?!AMP?! barfoo + flibble "not a # comment" +>) && + +( +cd foo && +> flibble "not a # comment") diff --git a/t/chainlint/inline-comment.test b/t/chainlint/inline-comment.test new file mode 100644 index 000000000000..8f26856e775b --- /dev/null +++ b/t/chainlint/inline-comment.test @@ -0,0 +1,12 @@ +( +# LINT: swallow inline comment (leaving command intact) + foobar && # comment 1 +# LINT: mispositioned "&&" (correctly) swallowed with comment + barfoo # wrong position for && +# LINT: "#" in string not misinterpreted as comment + flibble "not a # comment" +) && + +# LINT: "#" in string in cuddled subshell not misinterpreted as comment +(cd foo && + flibble "not a # comment") diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect new file mode 100644 index 000000000000..088e622c3141 --- /dev/null +++ b/t/chainlint/loop-in-if.expect @@ -0,0 +1,12 @@ +( + if true + then + while true + do +?!AMP?! echo "pop" + echo "glup" +?!AMP?! done + foo +?!AMP?! fi + bar +>) diff --git a/t/chainlint/loop-in-if.test b/t/chainlint/loop-in-if.test new file mode 100644 index 000000000000..93e8ba8e4d9a --- /dev/null +++ b/t/chainlint/loop-in-if.test @@ -0,0 +1,15 @@ +( + if true + then + while true + do +# LINT: missing "&&" on 'echo' + echo "pop" + echo "glup" +# LINT: missing "&&" on 'done' + done + foo +# LINT: missing "&&" on 'fi' + fi + bar +) diff --git a/t/chainlint/multi-line-nested-command-substitution.expect b/t/chainlint/multi-line-nested-command-substitution.expect new file mode 100644 index 000000000000..59b6c8b850a1 --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.expect @@ -0,0 +1,18 @@ +( + foo && + x=$( + echo bar | + cat +>> ) && + echo ok +>) | +sort && +( + bar && + x=$(echo bar | + cat +>> ) && + y=$(echo baz | +>> fip) && + echo fail +>) diff --git a/t/chainlint/multi-line-nested-command-substitution.test b/t/chainlint/multi-line-nested-command-substitution.test new file mode 100644 index 000000000000..300058341b6f --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.test @@ -0,0 +1,18 @@ +( + foo && + x=$( + echo bar | + cat + ) && + echo ok +) | +sort && +( + bar && + x=$(echo bar | + cat + ) && + y=$(echo baz | + fip) && + echo fail +) diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect new file mode 100644 index 000000000000..170cb5999322 --- /dev/null +++ b/t/chainlint/multi-line-string.expect @@ -0,0 +1,15 @@ +( + x="line 1 line 2 line 3" && +?!AMP?! y='line 1 line2' + foobar +>) && +( + echo "there's nothing to see here" && + exit +>) && +( + echo "xyz" "abc def ghi" && + echo 'xyz' 'abc def ghi' && + echo 'xyz' "abc def ghi" && + barfoo +>) diff --git a/t/chainlint/multi-line-string.test b/t/chainlint/multi-line-string.test new file mode 100644 index 000000000000..287ab8970548 --- /dev/null +++ b/t/chainlint/multi-line-string.test @@ -0,0 +1,27 @@ +( + x="line 1 + line 2 + line 3" && +# LINT: missing "&&" on assignment + y='line 1 + line2' + foobar +) && +( +# LINT: apostrophe (in a contraction) within string not misinterpreted as +# LINT: starting multi-line single-quoted string + echo "there's nothing to see here" && + exit +) && +( + echo "xyz" "abc + def + ghi" && + echo 'xyz' 'abc + def + ghi' && + echo 'xyz' "abc + def + ghi" && + barfoo +) diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect new file mode 100644 index 000000000000..cf18429d0397 --- /dev/null +++ b/t/chainlint/negated-one-liner.expect @@ -0,0 +1,5 @@ +! (foo && bar) && +! (foo && bar) >baz && + +?!SEMI?!! (foo; bar) && +?!SEMI?!! (foo; bar) >baz diff --git a/t/chainlint/negated-one-liner.test b/t/chainlint/negated-one-liner.test new file mode 100644 index 000000000000..c9598e915307 --- /dev/null +++ b/t/chainlint/negated-one-liner.test @@ -0,0 +1,7 @@ +# LINT: top-level one-liner subshell +! (foo && bar) && +! (foo && bar) >baz && + +# LINT: top-level one-liner subshell missing internal "&&" +! (foo; bar) && +! (foo; bar) >baz diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect new file mode 100644 index 000000000000..c2a59ffc335c --- /dev/null +++ b/t/chainlint/nested-cuddled-subshell.expect @@ -0,0 +1,19 @@ +( + (cd foo && + bar +>> ) && + (cd foo && + bar +?!AMP?!>> ) + ( + cd foo && +>> bar) && + ( + cd foo && +?!AMP?!>> bar) + (cd foo && +>> bar) && + (cd foo && +?!AMP?!>> bar) + foobar +>) diff --git a/t/chainlint/nested-cuddled-subshell.test b/t/chainlint/nested-cuddled-subshell.test new file mode 100644 index 000000000000..8fd656c7b598 --- /dev/null +++ b/t/chainlint/nested-cuddled-subshell.test @@ -0,0 +1,31 @@ +( +# LINT: opening "(" cuddled with first nested subshell statement + (cd foo && + bar + ) && + +# LINT: same but "&&" missing + (cd foo && + bar + ) + +# LINT: closing ")" cuddled with final nested subshell statement + ( + cd foo && + bar) && + +# LINT: same but "&&" missing + ( + cd foo && + bar) + +# LINT: "(" and ")" cuddled with first and final subshell statements + (cd foo && + bar) && + +# LINT: same but "&&" missing + (cd foo && + bar) + + foobar +) diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect new file mode 100644 index 000000000000..0c9ef1cfc695 --- /dev/null +++ b/t/chainlint/nested-here-doc.expect @@ -0,0 +1,7 @@ +cat >foop && + +( + cat && +?!AMP?! cat + foobar +>) diff --git a/t/chainlint/nested-here-doc.test b/t/chainlint/nested-here-doc.test new file mode 100644 index 000000000000..f35404bf0f93 --- /dev/null +++ b/t/chainlint/nested-here-doc.test @@ -0,0 +1,33 @@ +# LINT: inner "EOF" not misintrepreted as closing ARBITRARY here-doc +cat <<ARBITRARY >foop && +naddle +fub <<EOF + nozzle + noodle +EOF +formp +ARBITRARY + +( +# LINT: inner "EOF" not misintrepreted as closing INPUT_END here-doc + cat <<-\INPUT_END && + fish are mice + but geese go slow + data <<EOF + perl is lerp + and nothing else + EOF + toink + INPUT_END + +# LINT: same but missing "&&" + cat <<-\EOT + text goes here + data <<EOF + data goes here + EOF + more test here + EOT + + foobar +) diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect new file mode 100644 index 000000000000..15b68d437379 --- /dev/null +++ b/t/chainlint/nested-subshell-comment.expect @@ -0,0 +1,11 @@ +( + foo && + ( + bar && + # bottles wobble while fiddles gobble + # minor numbers of cows (or do they?) + baz && + snaff +?!AMP?!>> ) + fuzzy +>) diff --git a/t/chainlint/nested-subshell-comment.test b/t/chainlint/nested-subshell-comment.test new file mode 100644 index 000000000000..0ff136ab3cf1 --- /dev/null +++ b/t/chainlint/nested-subshell-comment.test @@ -0,0 +1,13 @@ +( + foo && + ( + bar && +# LINT: ")" in comment in nested subshell not misinterpreted as closing ")" + # bottles wobble while fiddles gobble + # minor numbers of cows (or do they?) + baz && + snaff +# LINT: missing "&&" on ')' + ) + fuzzy +) diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect new file mode 100644 index 000000000000..c8165ad19ec5 --- /dev/null +++ b/t/chainlint/nested-subshell.expect @@ -0,0 +1,12 @@ +( + cd foo && + ( + echo a && + echo b +>> ) >file && + cd foo && + ( + echo a + echo b +>> ) >file +>) diff --git a/t/chainlint/nested-subshell.test b/t/chainlint/nested-subshell.test new file mode 100644 index 000000000000..998b05a47d30 --- /dev/null +++ b/t/chainlint/nested-subshell.test @@ -0,0 +1,14 @@ +( + cd foo && + ( + echo a && + echo b + ) >file && + + cd foo && + ( +# LINT: nested multi-line subshell not presently checked for missing "&&" + echo a + echo b + ) >file +) diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect new file mode 100644 index 000000000000..237f22734963 --- /dev/null +++ b/t/chainlint/one-liner.expect @@ -0,0 +1,9 @@ +(foo && bar) && +(foo && bar) | +(foo && bar) >baz && + +?!SEMI?!(foo; bar) && +?!SEMI?!(foo; bar) | +?!SEMI?!(foo; bar) >baz + +(foo "bar; baz") diff --git a/t/chainlint/one-liner.test b/t/chainlint/one-liner.test new file mode 100644 index 000000000000..ec9acb98253d --- /dev/null +++ b/t/chainlint/one-liner.test @@ -0,0 +1,12 @@ +# LINT: top-level one-liner subshell +(foo && bar) && +(foo && bar) | +(foo && bar) >baz && + +# LINT: top-level one-liner subshell missing internal "&&" +(foo; bar) && +(foo; bar) | +(foo; bar) >baz + +# LINT: ";" in string not misinterpreted as broken &&-chain +(foo "bar; baz") diff --git a/t/chainlint/p4-filespec.expect b/t/chainlint/p4-filespec.expect new file mode 100644 index 000000000000..98b3d881fda9 --- /dev/null +++ b/t/chainlint/p4-filespec.expect @@ -0,0 +1,4 @@ +( + p4 print -1 //depot/fiddle#42 >file && + foobar +>) diff --git a/t/chainlint/p4-filespec.test b/t/chainlint/p4-filespec.test new file mode 100644 index 000000000000..4fd2d6e2b80b --- /dev/null +++ b/t/chainlint/p4-filespec.test @@ -0,0 +1,5 @@ +( +# LINT: Perforce revspec in filespec not misinterpreted as in-line comment + p4 print -1 //depot/fiddle#42 >file && + foobar +) diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect new file mode 100644 index 000000000000..211b901dbc42 --- /dev/null +++ b/t/chainlint/pipe.expect @@ -0,0 +1,8 @@ +( + foo | + bar | + baz && + fish | +?!AMP?! cow + sunder +>) diff --git a/t/chainlint/pipe.test b/t/chainlint/pipe.test new file mode 100644 index 000000000000..e6af4de91672 --- /dev/null +++ b/t/chainlint/pipe.test @@ -0,0 +1,12 @@ +( +# LINT: no "&&" needed on line ending with "|" + foo | + bar | + baz && + +# LINT: final line of pipe sequence ('cow') lacking "&&" + fish | + cow + + sunder +) diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect new file mode 100644 index 000000000000..1d79384606d2 --- /dev/null +++ b/t/chainlint/semicolon.expect @@ -0,0 +1,20 @@ +( +?!AMP?!?!SEMI?! cat foo ; echo bar +?!SEMI?! cat foo ; echo bar +>) && +( +?!SEMI?! cat foo ; echo bar && +?!SEMI?! cat foo ; echo bar +>) && +( + echo "foo; bar" && +?!SEMI?! cat foo; echo bar +>) && +( +?!SEMI?! foo; +>) && +( +cd foo && + for i in a b c; do +?!SEMI?! echo; +> done) diff --git a/t/chainlint/semicolon.test b/t/chainlint/semicolon.test new file mode 100644 index 000000000000..d82c8ebbc006 --- /dev/null +++ b/t/chainlint/semicolon.test @@ -0,0 +1,25 @@ +( +# LINT: missing internal "&&" and ending "&&" + cat foo ; echo bar +# LINT: final statement before ")" only missing internal "&&" + cat foo ; echo bar +) && +( +# LINT: missing internal "&&" + cat foo ; echo bar && + cat foo ; echo bar +) && +( +# LINT: not fooled by semicolon in string + echo "foo; bar" && + cat foo; echo bar +) && +( +# LINT: unnecessary terminating semicolon + foo; +) && +(cd foo && + for i in a b c; do +# LINT: unnecessary terminating semicolon + echo; + done) diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect new file mode 100644 index 000000000000..74723e734043 --- /dev/null +++ b/t/chainlint/subshell-here-doc.expect @@ -0,0 +1,11 @@ +( + echo wobba gorgo snoot wafta snurb && +?!AMP?! cat >bip + echo >bop +>) && +( + cat >bup && + cat >bup2 && + cat >bup3 && + meep +>) diff --git a/t/chainlint/subshell-here-doc.test b/t/chainlint/subshell-here-doc.test new file mode 100644 index 000000000000..f6b3ba4214a4 --- /dev/null +++ b/t/chainlint/subshell-here-doc.test @@ -0,0 +1,39 @@ +( +# LINT: stitch together incomplete \-ending lines +# LINT: swallow here-doc to avoid false positives in content + echo wobba \ + gorgo snoot \ + wafta snurb <<-EOF && + quoth the raven, + nevermore... + EOF + +# LINT: missing "&&" on 'cat' + cat <<EOF >bip + fish fly high + EOF + +# LINT: swallow here-doc (EOF is last line of subshell) + echo <<-\EOF >bop + gomez + morticia + wednesday + pugsly + EOF +) && +( +# LINT: swallow here-doc with arbitrary tag + cat <<-\ARBITRARY >bup && + glink + FIZZ + ARBITRARY + cat <<-'ARBITRARY2' >bup2 && + glink + FIZZ + ARBITRARY2 + cat <<-"ARBITRARY3" >bup3 && + glink + FIZZ + ARBITRARY3 + meep +) diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect new file mode 100644 index 000000000000..51162821d7e1 --- /dev/null +++ b/t/chainlint/subshell-one-liner.expect @@ -0,0 +1,14 @@ +( + (foo && bar) && + (foo && bar) | + (foo && bar) >baz && +?!SEMI?! (foo; bar) && +?!SEMI?! (foo; bar) | +?!SEMI?! (foo; bar) >baz && + (foo || exit 1) && + (foo || exit 1) | + (foo || exit 1) >baz && +?!AMP?! (foo && bar) +?!AMP?!?!SEMI?! (foo && bar; baz) + foobar +>) diff --git a/t/chainlint/subshell-one-liner.test b/t/chainlint/subshell-one-liner.test new file mode 100644 index 000000000000..37fa643c20a9 --- /dev/null +++ b/t/chainlint/subshell-one-liner.test @@ -0,0 +1,24 @@ +( +# LINT: nested one-liner subshell + (foo && bar) && + (foo && bar) | + (foo && bar) >baz && + +# LINT: nested one-liner subshell missing internal "&&" + (foo; bar) && + (foo; bar) | + (foo; bar) >baz && + +# LINT: nested one-liner subshell with "|| exit" + (foo || exit 1) && + (foo || exit 1) | + (foo || exit 1) >baz && + +# LINT: nested one-liner subshell lacking ending "&&" + (foo && bar) + +# LINT: nested one-liner subshell missing internal "&&" and lacking ending "&&" + (foo && bar; baz) + + foobar +) diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect new file mode 100644 index 000000000000..c9913429e64b --- /dev/null +++ b/t/chainlint/t7900-subtree.expect @@ -0,0 +1,10 @@ +( + chks="sub1sub2sub3sub4" && + chks_sub=$(cat | sed 's,^,sub dir/,' +>>) && + chkms="main-sub1main-sub2main-sub3main-sub4" && + chkms_sub=$(cat | sed 's,^,sub dir/,' +>>) && + subfiles=$(git ls-files) && + check_equal "$subfiles" "$chkms$chks" +>) diff --git a/t/chainlint/t7900-subtree.test b/t/chainlint/t7900-subtree.test new file mode 100644 index 000000000000..277d8358dfd5 --- /dev/null +++ b/t/chainlint/t7900-subtree.test @@ -0,0 +1,22 @@ +( + chks="sub1 +sub2 +sub3 +sub4" && + chks_sub=$(cat <<TXT | sed 's,^,sub dir/,' +$chks +TXT +) && + chkms="main-sub1 +main-sub2 +main-sub3 +main-sub4" && + chkms_sub=$(cat <<TXT | sed 's,^,sub dir/,' +$chkms +TXT +) && + + subfiles=$(git ls-files) && + check_equal "$subfiles" "$chkms +$chks" +) diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect new file mode 100644 index 000000000000..13cff2c0a511 --- /dev/null +++ b/t/chainlint/while-loop.expect @@ -0,0 +1,11 @@ +( + while true + do +?!AMP?! echo foo + cat +?!AMP?! done + while true; do + echo foo && + cat bar + done +>) diff --git a/t/chainlint/while-loop.test b/t/chainlint/while-loop.test new file mode 100644 index 000000000000..f1df085bf03b --- /dev/null +++ b/t/chainlint/while-loop.test @@ -0,0 +1,19 @@ +( +# LINT: 'while, 'do', 'done' do not need "&&" + while true + do +# LINT: missing "&&" on 'echo' + echo foo +# LINT: last statement of while does not need "&&" + cat <<-\EOF + bar + EOF +# LINT: missing "&&" on 'done' + done + +# LINT: 'do' on same line as 'while' + while true; do + echo foo && + cat bar + done +) |