name: "Options: errtrace (-E)"
cases:
  #
  # Basic errtrace option behavior
  #
  - name: "errtrace disabled by default"
    stdin: |
      set +E 2>/dev/null || true
      echo "errtrace test"

  - name: "errtrace can be enabled and disabled"
    stdin: |
      set -E
      echo "enabled: $-" | grep -q E && echo "E is set"
      set +E
      echo "disabled: $-" | grep -qv E && echo "E is unset"

  #
  # ERR trap inheritance in functions (core errtrace behavior)
  #
  - name: "errtrace disabled - functions don't inherit ERR trap"
    stdin: |
      set +E
      trap 'echo "ERR trapped"' ERR
      myfunc() { false; }
      myfunc
      echo "after"

  - name: "errtrace enabled - functions inherit ERR trap"
    stdin: |
      set -E
      trap 'echo "ERR trapped"' ERR
      myfunc() { false; }
      myfunc
      echo "after"

  - name: "errtrace with nested functions"
    stdin: |
      set -E
      trap 'echo "ERR trapped"' ERR
      inner() { false; }
      outer() { inner; }
      outer
      echo "after"

  - name: "errtrace toggling mid-script"
    stdin: |
      trap 'echo "ERR trapped"' ERR
      set -E
      myfunc1() { false; }
      myfunc1
      echo "after first call"
      set +E
      myfunc2() { false; }
      myfunc2
      echo "after second call"

  #
  # ERR trap inheritance in subshells
  #
  - name: "errtrace disabled - subshell doesn't inherit ERR trap"
    stdin: |
      set +E
      trap 'echo "ERR"' ERR
      (
        trap -p ERR
        false
        echo "no ERR trap fired"
      )
      echo "after"

  - name: "errtrace enabled - subshell inherits ERR trap"
    stdin: |
      set -E
      trap 'echo "ERR"' ERR
      (
        trap -p ERR | grep -q ERR && echo "ERR trap inherited"
        false
        echo "after false in subshell"
      )
      echo "after"

  #
  # ERR trap inheritance in command substitution
  #
  - name: "errtrace disabled - command substitution doesn't inherit ERR trap"
    stdin: |
      set +E
      trap 'echo "[ERR trapped]" >&2' ERR
      result=$(trap -p ERR; false; echo "no trap inherited")
      echo "result: $result"

  - name: "errtrace enabled - command substitution inherits ERR trap"
    stdin: |
      set -E
      trap 'echo "[ERR in subshell]" >&2' ERR
      result=$(false; echo "after false in subshell")
      echo "result: $result"

  #
  # ERR trap inheritance in pipelines
  #
  - name: "errtrace with pipeline - last command fails"
    stdin: |
      set -E
      trap 'echo "[ERR: $?]" >&2' ERR
      echo "data" | cat | false
      echo "after pipeline"

  - name: "errtrace with pipeline - middle command fails (pipefail)"
    stdin: |
      set -E
      set -o pipefail
      trap 'echo "[ERR: $?]" >&2' ERR
      echo "data" | false | cat
      echo "after pipeline"

  - name: "errtrace - ERR trap in pipeline subshells"
    stdin: |
      set -E
      trap 'echo "[ERR: $BASH_COMMAND]" >&2' ERR
      echo "input" | { false; echo "after false in brace"; }
      echo "done"

  #
  # ERR trap with errexit interaction
  #
  - name: "errtrace with errexit - ERR trap fires before exit"
    stdin: |
      set -e
      set -E
      trap 'echo "ERR trap fired"' ERR
      false
      echo "should not print"

  - name: "errtrace with errexit in function"
    known_failure: true # TODO(traps): ERR trap not firing in function with errexit
    stdin: |
      set -e
      set -E
      trap 'echo "ERR trap"' ERR
      myfunc() { false; }
      myfunc
      echo "should not print"

  #
  # ERR trap inheritance in deeply nested functions
  #
  - name: "errtrace - ERR trap in deeply nested function"
    stdin: |
      set -E
      trap 'echo "ERR at level ${#FUNCNAME[@]}"' ERR
      level3() { false; }
      level2() { level3; }
      level1() { level2; }
      level1
      echo "after"

  #
  # ERR trap modification within functions
  #
  - name: "errtrace - ERR trap can be changed inside function"
    stdin: |
      set -E
      trap 'echo "outer ERR"' ERR
      myfunc() {
        trap 'echo "inner ERR"' ERR
        false
      }
      myfunc
      false
      echo "after"

  - name: "errtrace - ERR trap can be cleared inside function"
    stdin: |
      set -E
      trap 'echo "ERR"' ERR
      myfunc() {
        trap - ERR
        false
        echo "no ERR in func"
      }
      myfunc
      false
      echo "after"

  #
  # ERR trap in background jobs with errtrace
  #
  - name: "errtrace - ERR trap in background job"
    stdin: |
      set -E
      trap 'echo "ERR" >&2' ERR
      { false; echo "bg done"; } &
      wait
      echo "main done"

  #
  # Sourced scripts with errtrace
  #
  - name: "errtrace - ERR trap inherited in sourced script"
    test_files:
      - path: "failing.sh"
        contents: |
          echo "in sourced"
          false
          echo "after false in sourced"
    stdin: |
      set -E
      trap 'echo "ERR trapped"' ERR
      . ./failing.sh
      echo "after source"

