diff options
Diffstat (limited to 't/chainlint')
74 files changed, 946 insertions, 0 deletions
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect new file mode 100644 index 0000000000..09457d3196 --- /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 0000000000..16206960d8 --- /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 0000000000..c4a830d1c1 --- /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 0000000000..92bbb777b8 --- /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 0000000000..3be939ed38 --- /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 0000000000..f6dd14302b --- /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 0000000000..fed7e89ae8 --- /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 0000000000..d859151af1 --- /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 0000000000..55b0f42a53 --- /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 0000000000..3cc67b65d0 --- /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 0000000000..41f121fbbf --- /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 0000000000..5ef6ff7db5 --- /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 0000000000..2a910f9d66 --- /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 0000000000..72d482f76d --- /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 0000000000..184688718a --- /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 0000000000..508ca447fd --- /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 0000000000..ad4118e537 --- /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 0000000000..3bbb002a4c --- /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 0000000000..3be939ed38 --- /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 0000000000..113c0c466f --- /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 0000000000..9674b88cf2 --- /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 0000000000..571bbd85cd --- /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 0000000000..ab2a026fbc --- /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 0000000000..eed774a9d6 --- /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 0000000000..8c0260d7f1 --- /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 0000000000..a841d781f0 --- /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 0000000000..b506d46221 --- /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 0000000000..0499fa4180 --- /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 0000000000..84d8bdebc0 --- /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 0000000000..2f038207e1 --- /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 0000000000..bf78454f74 --- /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 0000000000..4e6ab69b88 --- /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 0000000000..c33cf56ee7 --- /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 0000000000..7db76262bc --- /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.expect b/t/chainlint/here-doc.expect new file mode 100644 index 0000000000..2328fe7753 --- /dev/null +++ b/t/chainlint/here-doc.expect @@ -0,0 +1,3 @@ +boodle wobba gorgo snoot wafta snurb && + +horticulture diff --git a/t/chainlint/here-doc.test b/t/chainlint/here-doc.test new file mode 100644 index 0000000000..bd36f6e1d3 --- /dev/null +++ b/t/chainlint/here-doc.test @@ -0,0 +1,16 @@ +# 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 (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 0000000000..03d3ceb22d --- /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 0000000000..daf22da164 --- /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 0000000000..5953c7bfbc --- /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 0000000000..9bd8e9a4c6 --- /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 0000000000..2f3ebabdc2 --- /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 0000000000..d856658083 --- /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 0000000000..fc9f250ac4 --- /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 0000000000..8f26856e77 --- /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 0000000000..088e622c31 --- /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 0000000000..93e8ba8e4d --- /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 0000000000..19c023b1c8 --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.expect @@ -0,0 +1,9 @@ +( + foo && + x=$( + echo bar | + cat +>> ) && + echo ok +>) | +sort 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 0000000000..ca0620ab6b --- /dev/null +++ b/t/chainlint/multi-line-nested-command-substitution.test @@ -0,0 +1,9 @@ +( + foo && + x=$( + echo bar | + cat + ) && + echo ok +) | +sort diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect new file mode 100644 index 0000000000..8334c4cc8e --- /dev/null +++ b/t/chainlint/multi-line-string.expect @@ -0,0 +1,9 @@ +( + x=line 1 line 2 line 3" && +?!AMP?! y=line 1 line2' + foobar +>) && +( + echo "there's nothing to see here" && + exit +>) diff --git a/t/chainlint/multi-line-string.test b/t/chainlint/multi-line-string.test new file mode 100644 index 0000000000..14cb44d51c --- /dev/null +++ b/t/chainlint/multi-line-string.test @@ -0,0 +1,15 @@ +( + 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 +) diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect new file mode 100644 index 0000000000..cf18429d03 --- /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 0000000000..c9598e9153 --- /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 0000000000..c2a59ffc33 --- /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 0000000000..8fd656c7b5 --- /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 0000000000..559301e005 --- /dev/null +++ b/t/chainlint/nested-here-doc.expect @@ -0,0 +1,5 @@ +( + 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 0000000000..027e0bb3ff --- /dev/null +++ b/t/chainlint/nested-here-doc.test @@ -0,0 +1,23 @@ +( +# 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 0000000000..15b68d4373 --- /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 0000000000..0ff136ab3c --- /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 0000000000..c8165ad19e --- /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 0000000000..998b05a47d --- /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 0000000000..237f227349 --- /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 0000000000..ec9acb9825 --- /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 0000000000..98b3d881fd --- /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 0000000000..4fd2d6e2b8 --- /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 0000000000..211b901dbc --- /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 0000000000..e6af4de916 --- /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 0000000000..1d79384606 --- /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 0000000000..d82c8ebbc0 --- /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 0000000000..19d5aff233 --- /dev/null +++ b/t/chainlint/subshell-here-doc.expect @@ -0,0 +1,5 @@ +( + echo wobba gorgo snoot wafta snurb && +?!AMP?! cat >bip + echo >bop +>) diff --git a/t/chainlint/subshell-here-doc.test b/t/chainlint/subshell-here-doc.test new file mode 100644 index 0000000000..9c3564c247 --- /dev/null +++ b/t/chainlint/subshell-here-doc.test @@ -0,0 +1,23 @@ +( +# 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 +) diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect new file mode 100644 index 0000000000..51162821d7 --- /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 0000000000..37fa643c20 --- /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/while-loop.expect b/t/chainlint/while-loop.expect new file mode 100644 index 0000000000..13cff2c0a5 --- /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 0000000000..f1df085bf0 --- /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 +) |