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: "Basic 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 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 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 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
