Files
sausage/userland/brush/source/brush-shell/tests/cases/compat/here.yaml
T
2026-11-11 22:04:16 +00:00

743 lines
16 KiB
YAML

name: "Here docs/strings"
cases:
- name: "Basic here doc"
stdin: |
cat <<END-MARKER
Something here...
...and here.
END-MARKER
echo "This is after"
- name: "Basic here doc in a script"
test_files:
- path: "script.sh"
contents: |
cat <<END-MARKER
Something here...
...and here.
END-MARKER
echo "This is after"
args: ["./script.sh"]
- name: "Here doc in a function"
stdin: |
function myfunc() {
if true
then
cat << END-MARKER
Something here...
END-MARKER
fi
}
myfunc
- name: "Here doc with expansions"
stdin: |
cat <<END-MARKER
Something here...
...and here.
$(echo "This is after")
END-MARKER
- name: "Here doc with expansions but quoted tag"
stdin: |
cat <<"END-MARKER"
Something here...
...and here.
$(echo "This is after")
END-MARKER
- name: "Here doc with tab removal"
stdin: |
cat <<-END-MARKER
Something here...
...and here.
END-MARKER
- name: "Basic here string"
stdin: |
shopt -ou posix
cat <<<"Something here."
wc -l <<<"Something"
- name: "Empty here doc"
stdin: |
wc -l <<EOF
EOF
- name: "Single-line here doc"
stdin: "wc -l <<EOF\nSomething\nEOF"
- name: "Here doc with other tokens after tag"
stdin: |
wc -l <<EOF | wc -l
A B C
1 2 3
EOF
- name: "Multiple here docs"
stdin: |
cat <<EOF1 <<EOF2
A B C
EOF1
1 2 3
EOF2
- name: "Here doc in a command substitution"
stdin: |
test1=$(cat <<EOF
1
2 3
4 5 6
EOF
)
echo "${test1}"
- name: "Here doc in a double-quoted command substitution"
stdin: |
test1="$(cat <<EOF
something
EOF
)"
echo "${test1}"
- name: "Here doc in a double-quoted command substitution with spaces"
stdin: |
test1="$(cat << EOF
something
EOF
)"
echo "${test1}"
- name: "Here doc in a command substitution with quotes"
stdin: |
test1=$(cat <<EOF
something "quoted"
EOF
)
echo "${test1}"
- name: "Here doc with parameter default containing quotes"
stdin: |
cat <<EOF
${unset_var:-"default value"}
EOF
- name: "Here doc preserves literal double quotes"
stdin: |
cat <<EOF
"double quoted"
she said "hello"
EOF
- name: "Here doc preserves literal single quotes"
stdin: |
cat <<EOF
'single quoted'
it's a test
EOF
- name: "Here doc with mixed quotes and expansion"
stdin: |
x=world
cat <<EOF
"hello $x"
"$x" and more
EOF
- name: "Here doc does not perform brace expansion"
stdin: |
cat <<EOF
{a,b,c}
{1..3}
EOF
- name: "Here doc does not perform tilde expansion"
stdin: |
cat <<EOF
~
~/path
EOF
- name: "Here doc escape sequences"
stdin: |
cat <<EOF
\$HOME
\\backslash
\n not a newline
\"not unquoted\"
\'not unquoted\'
EOF
- name: "Here doc line continuation"
stdin: |
cat <<EOF
alpha\
beta
double\\
backslash
$(echo 'single\
quotes') `echo back\
quotes`
EOF
cat <<'EOF'
alpha\
beta
EOF
cat <<\EOF
alpha\
beta $HOME
EOF
cat <<'EOF'
\
quoted body starting with a line continuation
EOF
- name: "Here doc backquote escape rules"
stdin: |
cat <<EOF
`echo \"q\"`
`echo \\\\z`
EOF
- name: "Here doc end tag joined by a line continuation"
stdin: |
cat <<EOF
body
E\
OF
echo after
cat <<EOF
body\
EOF
EOF
- name: "Here doc end tag line continued onto the next line"
stdin: |
cat <<E
abc
E\
X
E
echo done
- name: "Here doc line continuation with tab stripping"
stdin: "cat <<-EOF\n\talpha\\\n\tbeta\n\tEOF\n"
- name: "Here doc with command substitution containing quotes"
stdin: |
cat <<EOF
$(echo "hello world")
$(echo 'single')
EOF
- name: "Here doc with arithmetic expansion"
stdin: |
cat <<EOF
$((2 + 3))
$((10 * 2))
EOF
- name: "Here doc in a command substitution with parentheses"
stdin: |
test1=$(cat <<EOF
(something)
EOF
)
echo "${test1}"
- name: "Here doc in a command substitution inside arithmetic"
stdin: |
echo $(( $(cat <<EOF
1
EOF
) + 2 ))
- name: "Here doc body closing paren in a command substitution inside arithmetic"
known_failure: true # TODO(tokenizer): bash runs the body's `)` as a command, expanding `$((...))` to nothing; brush reads the body and fails to evaluate `) + 2`
ignore_stderr: true
stdin: |
echo $(( $(cat <<EOF
)
EOF
) + 2 ))
echo "rc=$?"
- name: "Here doc with parentheses"
stdin: |
cat <<EOF
(something)
EOF
- name: "Multiple here docs in a command substitution"
stdin: |
test1=$(cat <<EOF1 <<EOF2
A B C
EOF1
D E F
EOF2
)
echo "${test1}"
- name: "Complex here docs in a command substitution"
stdin: |
test1=$(cat <<EOF1 <<EOF2 | wc -l
A B C
EOF1
D E F
EOF2
)
echo "${test1}"
- name: "Here doc with quoted delimiter"
stdin: |
cat <<'EOF'
something
EOF
- name: "Here doc with quoted delimiter containing backslashes and quotes"
stdin: |
cat <<'a\b'
single
a\b
cat <<"a\b"
double
a\b
cat <<"x'y"
mixed
x'y
cat <<a\'b
escaped
a'b
- name: "Here doc with double quoted delimiter"
stdin: |
cat <<"EOF"
something
EOF
- name: "Here doc with quoted delimiter inside command substitution"
stdin: |
$(cat <<'EOF'
true
EOF
)
- name: "Here doc with double quoted delimiter inside command substitution"
stdin: |
$(cat <<"EOF"
true
EOF
)
- name: "Here doc with unpaired single quote in command substitution"
stdin: |
echo "$(cat <<'EOF'
it's here
EOF
)"
- name: "Here doc with unpaired backtick in command substitution"
stdin: |
echo "$(cat <<'EOF'
a ` b
EOF
)"
- name: "Here doc with three single quotes in command substitution"
stdin: |
echo "$(cat <<'EOF'
it's Bob's it's
EOF
)"
- name: "Here doc with unpaired single quote in command substitution (#420)"
stdin: |
var=$(
sed 's/nice/cool/' - <<-EOF
that's
"nice"
EOF
)
echo $var
- name: "Here doc with unpaired double quote in command substitution (#1066)"
stdin: |
echo "$(cat <<'EOF'
she said "hello
EOF
)"
- name: "Here doc with all three unmatched delimiters in command substitution (#1066)"
stdin: |
echo "$(cat <<'EOF'
`hello "world it's
EOF
)"
- name: "Here doc with quoted parens and backticks in command substitution (#1066)"
stdin: |
printf '%s\n' "$(cat <<'EOF'
a (b's c) `touch pwned` d's
EOF
)"
- name: "Here doc with unpaired close paren in command substitution"
stdin: |
echo "$(cat <<END
This one: “)”
END
)"
- name: "Here doc body starting with close paren in command substitution"
stdin: |
x=$(cat <<END
)
END
)
echo "x=$x"
echo $(cat <<END
) two
END
)
cat <<OUTER
$(cat <<END
) three
END
)
OUTER
- name: "Here doc in command substitution in parameter default"
stdin: |
echo "${unset_var:-$(cat <<'EOF'
she said "hello ) it's
EOF
)}"
- name: "Multiple here docs with unbalanced quotes in command substitution"
stdin: |
echo "$(cat <<A <<'B'
a "1
A
b )2 it's
B
)"
- name: "Tab-stripped here doc with unbalanced quotes in command substitution"
stdin: |
echo "$(cat <<-'EOF'
tab "stripped )
EOF
)"
- name: "Here doc body containing command substitution with its own here doc"
stdin: |
cat <<EOF
body $(cat <<'INNER'
inner "quote ) it's
INNER
) end
EOF
- name: "Eval of here doc with unbalanced quotes in command substitution"
stdin: |
eval 'echo "$(cat <<EOF
ev "al )
EOF
)"'
- name: "Here doc with unterminated command substitution"
ignore_stderr: true
stdin: |
cat <<EOF
a $(echo hi b
EOF
echo "rc=$?"
- name: "Here doc with unterminated parameter expansion"
known_failure: true # TODO(expansion): #540: unterminated '${' is silently treated as literal text
ignore_stderr: true
stdin: |
cat <<EOF
a ${USER b
EOF
echo "rc=$?"
- name: "Here doc with command substitution that never closes"
ignore_stderr: true
stdin: |
cat <<EOF
a $(echo 'b) c
EOF
echo "rc=$?"
cat <<EOF
a $(echo b # c)
EOF
echo "rc=$?"
- name: "Here doc with unterminated arithmetic expansions"
ignore_stderr: true
stdin: |
cat <<EOF
a $((1 + b
EOF
echo "rc=$?"
cat <<EOF
a $[1 + b
EOF
echo "rc=$?"
- name: "Here doc tag containing command substitution"
stdin: |
cat <<$(x)
body
$(x)
- name: "Here doc tag containing parameter expansion"
stdin: |
cat <<E${x}
body
E${x}
- name: "Here doc tag containing arithmetic expansion"
stdin: |
cat <<$((1 + 2))
body
$((1 + 2))
cat <<$[1]
body
$[1]
- name: "Expansions after here doc tag on the same line"
stdin: |
printf '[%s]\n' <<EOF $(echo a b) "$((1 + 2))" "${x:-y}" $[4]
ignored
EOF
- name: "Here doc in command substitution with multiple blanks before tag"
stdin: |
echo "$(cat << EOF
two blanks
EOF
)"
echo "$(cat <<- EOF
two tabs
EOF
)"
- name: "Here doc in command substitution on the same line as another here doc"
stdin: |
cat <<A; echo "$(cat <<B
inner body
B
)"
outer body
A
- name: "Here doc started in command substitution with body after it"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
tr a-z A-Z <<<"[$(cat <<EOF)]"
body
EOF
echo after
- name: "Here doc started in command substitution while another here doc is pending"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
cat <<A; echo "[$(cat <<B)]"
b body
B
a body
A
echo "[$(cat <<C)]" "[$(cat <<D)]"
c body
C
d body
D
- name: "Here doc started in nested command substitution with body after it"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
echo $(echo $(cat <<EOF)
body
EOF
echo more
)
- name: "Here doc started in doubly nested command substitution with body after it"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
echo "[$(echo $(cat <<EOF))]"
body
EOF
- name: "Here doc started in command substitution in parameter expansion with body after it"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
echo "[${x:-$(cat <<EOF)}]"
body
EOF
- name: "Here doc started in command substitution with commands after it and body after it"
ignore_stderr: true # bash warns about the unterminated here-documents
stdin: |
echo "[$(cat <<EOF | tr a-z A-Z)]"
body
EOF
echo "[$(cat <<A; cat <<-B)]"
a
A
b
B
- name: "Here doc started in command substitution in command with its own here doc"
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
f() { echo "arg=$1"; cat; }
f "[$(cat <<B)]" <<A
b
B
a
A
- name: "Here doc started in command substitution with line continuation after it"
known_failure: true # TODO(input): reading a line at a time, the check for a trailing line continuation misses one set aside until after the body, so the command runs without the line it continues onto
ignore_stderr: true # bash warns about the unterminated here-document
stdin: |
echo "[$(cat <<EOF)]" \
more
body
EOF
echo after
- name: "Here doc operator with no tag in command substitution"
ignore_stderr: true
stdin: |
echo "[$(cat <<)]"
echo after
- name: "Here doc operator inside parameter expansion is literal"
stdin: |
echo ${x:-<<}
echo ${x:-<< foo}
echo "${x:-a<<b}"
echo ${x:-<<-EOF}
echo after
- name: "Blanks and operators inside parameter expansion word"
stdin: |
echo "[${x:- | }]" "[${x:-a b}]" "[${x:-a;b}]" "[${x:- #y}]" "[${x:-a #b}]"
echo "[${x:-(a) && b}]"
- name: "Shift operator after nested arithmetic expansion"
stdin: |
echo $(( $((1)) << 2 ))
echo $[ $((1)) << 3 ]
(( x = $((1)) << 4 )); echo "$x"
- name: "Here doc after arithmetic command in command substitution"
stdin: |
x=$( ((1)) ); cat <<EOF
body
EOF
- name: "Here doc after arithmetic command inside command substitution"
stdin: |
x=$( ((1)); cat <<EOF
a)b
EOF
)
echo "[$x]"
- name: "Shift operator after parenthesized arithmetic in arithmetic expansion"
stdin: |
echo $(( ((1)) << 2 )) $[ ((1)) << 3 ]
- name: "Here doc in subshell in command substitution"
stdin: |
x=$( (cat <<EOF; echo x) | tr a-z A-Z
body
EOF
)
echo "[$x]"
- name: "Here doc pending while a later expansion spans lines"
stdin: |
cat <<A; echo "$(echo x
echo y)"
a
A
cat <<B; echo "${x:-p
q}"
b
B
cat <<C; echo $[ 1 +
2 ]
c
C
- name: "Here doc body with command substitution that leaves a here doc open"
ignore_stderr: true # bash warns about the unterminated here-documents
stdin: |
cat <<X
a $(cat <<EOF) b
X
echo "rc=$?"
- name: "Here doc body with command substitution that doesn't parse"
known_failure: true # TODO(expansion): bash fails the command when a substitution in the body doesn't parse; brush runs it with the substitution empty
ignore_stderr: true
stdin: |
cat <<X
a $(if) b
X
echo "rc=$?"
- name: "Here doc tag quote removal with nested quotes and backslashes"
ignore_stderr: true
stdin: |
cat <<"'"
a
'
cat <<'"x"'
b
"x"
cat <<'a\b'
c
a\b
echo after
- name: "Here doc tag with ANSI-C quoting"
known_failure: true # TODO(tokenizer): $'...' in a here tag isn't decoded, so the tag is never matched
ignore_stderr: true
stdin: |
cat <<$'E\x4fF'
a
EOF
echo after
- name: "Here doc delimited by end of input"
known_failure: true # TODO(tokenizer): bash warns and ends the body at the end of the input; brush rejects the script
ignore_stderr: true
stdin: |
cat <<EOF
body
- name: "Here doc in command substitution closed on its tag line"
known_failure: true # TODO(tokenizer): bash ends the body at a line holding the tag followed by the substitution's ')'
ignore_stderr: true
stdin: |
x=$(cat <<EOF
body
EOF)
echo "[$x]"