name: "Options: set -u"
cases:
  # Basic behavior
  - name: "Basic set variable access"
    stdin: |
      set -u
      var="value"
      echo "$var"

  - name: "Unset variable triggers error"
    ignore_stderr: true
    stdin: |
      set -u
      echo "$unset_var"
      echo "should not print"

  - name: "Command line -u"
    args: ["-u"]
    ignore_stderr: true
    stdin: |
      echo "$unset_var"
      echo "should not print"

  # Special parameters - should NOT error even when unset
  - name: "Special parameter $@ does not error"
    stdin: |
      set -u
      echo "args: $@"

  - name: "Special parameter $* does not error"
    stdin: |
      set -u
      echo "args: $*"

  - name: "Special parameter $# does not error"
    stdin: |
      set -u
      echo "count: $#"

  - name: "Special parameter $? does not error"
    stdin: |
      set -u
      true
      echo "status: $?"

  - name: "Special parameter $$ does not error"
    stdin: |
      set -u
      echo "pid: $$" > /dev/null
      echo "ok"

  - name: "Special parameter $! does not error when no background jobs"
    known_failure: true
    ignore_stderr: true
    stdin: |
      set -u
      echo "last bg: ${!}" || echo "ok"

  - name: "Special parameter $0 does not error"
    stdin: |
      set -u
      echo "shell: $0" > /dev/null
      echo "ok"

  - name: "Special parameter $- does not error"
    stdin: |
      set -u
      echo "flags: $-" > /dev/null
      echo "ok"

  # Positional parameters
  - name: "Unset positional parameter triggers error"
    ignore_stderr: true
    stdin: |
      set -u
      myfunc() {
        echo "$1"
      }
      myfunc
      echo "should not print"

  - name: "Set positional parameter does not error"
    stdin: |
      set -u
      myfunc() {
        echo "$1"
      }
      myfunc "arg"

  - name: "Positional parameters beyond provided args error"
    ignore_stderr: true
    stdin: |
      set -u
      myfunc() {
        echo "$2"
      }
      myfunc "only_one_arg"
      echo "should not print"

  # Parameter expansion forms
  - name: "Unset variable with default does not error"
    stdin: |
      set -u
      echo "${unset_var:-default}"

  - name: "Empty vs unset with :- operator"
    stdin: |
      set -u
      empty=""
      echo "${empty:-default}"
      echo "${unset:-default}"

  - name: "Empty vs unset with - operator"
    stdin: |
      set -u
      empty=""
      echo "${empty-default}"
      echo "${unset-default}"

  # Arrays (if supported)
  - name: "Unset array element with default"
    stdin: |
      set -u
      arr=(a b c)
      echo "${arr[10]:-default}"

  - name: "Unset array treated as unset variable"
    stdin: |
      set -u
      echo "${unset_array[@]}"
      echo "should not print"

  - name: "Unset array with default does not error"
    stdin: |
      set -u
      echo "${unset_array[@]:-default}"

  # Conditionals
  - name: "Unset variable in conditional test errors"
    ignore_stderr: true
    stdin: |
      set -u
      if [ "$unset_var" = "value" ]; then
        echo "then"
      fi
      echo "should not print"

  - name: "Unset variable in [[ test errors"
    ignore_stderr: true
    stdin: |
      set -u
      if [[ $unset_var = "value" ]]; then
        echo "then"
      fi
      echo "should not print"

  - name: "Unset variable with default in conditional works"
    stdin: |
      set -u
      if [ "${unset_var:-}" = "" ]; then
        echo "empty"
      fi

  - name: "test -v for unset variable"
    stdin: |
      set -u
      if test -v unset_var; then
        echo "set"
      else
        echo "unset"
      fi

  - name: "test -z with unset variable errors"
    ignore_stderr: true
    stdin: |
      set -u
      if test -z "$unset_var"; then
        echo "empty"
      fi
      echo "should not print"

  # Command substitution
  - name: "Unset variable in command substitution errors"
    ignore_stderr: true
    stdin: |
      set -u
      result=$(echo "$unset_var")
      echo "should not print"

  - name: "Unset variable with default in command substitution"
    stdin: |
      set -u
      result=$(echo "${unset_var:-default}")
      echo "$result"

  # Arithmetic expansion
  - name: "Unset variable in arithmetic defaults to zero"
    ignore_stderr: true
    stdin: |
      set -u
      result=$((unset_var + 5))
      echo "$result"

  # set +u to disable
  - name: "set +u disables unset variable check"
    stdin: |
      set -u
      set +u
      echo "$unset_var"
      echo "ok"

  - name: "set -u can be re-enabled"
    ignore_stderr: true
    stdin: |
      set -u
      set +u
      echo "$unset_var"
      set -u
      echo "$another_unset"
      echo "should not print"

  - name: "set +u in function does not affect parent"
    stdin: |
      set -u
      myfunc() {
        set +u
        echo "$unset_in_func"
      }
      myfunc
      echo "$unset_in_parent"
      echo "should not print"

  # Functions
  - name: "Unset variable in function body errors"
    ignore_stderr: true
    stdin: |
      set -u
      myfunc() {
        echo "$unset_var"
      }
      myfunc
      echo "should not print"

  - name: "Local unset variable errors"
    ignore_stderr: true
    stdin: |
      set -u
      myfunc() {
        local unset_local
        echo "$unset_local"
      }
      myfunc
      echo "should not print"

  - name: "Local variable declaration with value works"
    stdin: |
      set -u
      myfunc() {
        local my_var="value"
        echo "$my_var"
      }
      myfunc

  - name: "Function parameter shadows unset global"
    stdin: |
      set -u
      myfunc() {
        local var="$1"
        echo "$var"
      }
      myfunc "arg"

  # Subshells
  - name: "Unset variable in subshell errors"
    ignore_stderr: true
    stdin: |
      set -u
      (echo "$unset_var")
      echo "should not print"

  - name: "set +u in subshell does not affect parent"
    ignore_stderr: true
    stdin: |
      set -u
      (
        set +u
        echo "$unset_in_subshell"
      )
      echo "$unset_in_parent"
      echo "should not print"

  # Variable assignment and unset
  - name: "Variable set then unset errors on access"
    ignore_stderr: true
    stdin: |
      set -u
      var="value"
      echo "$var"
      unset var
      echo "$var"
      echo "should not print"

  - name: "Variable set then unset with default works"
    stdin: |
      set -u
      var="value"
      unset var
      echo "${var:-default}"

  - name: "Unsetting non-existent variable does not error"
    stdin: |
      set -u
      unset non_existent
      echo "ok"

  # Export and environment
  - name: "Exported unset variable errors"
    ignore_stderr: true
    stdin: |
      set -u
      export unset_exported
      echo "$unset_exported"
      echo "should not print"

  - name: "Exported variable with value works"
    stdin: |
      set -u
      export exported_var="value"
      echo "$exported_var"

  # Pattern expansion
  - name: "Unset variable in pattern errors"
    ignore_stderr: true
    stdin: |
      set -u
      echo ${unset_var#prefix}
      echo "should not print"

  # Length operator
  - name: "Length of unset variable errors"
    ignore_stderr: true
    stdin: |
      set -u
      echo ${#unset_var}
      echo "should not print"

  - name: "Length of empty variable works"
    stdin: |
      set -u
      empty=""
      echo ${#empty}

  # Indirect expansion
  - name: "Indirect expansion of unset variable errors"
    ignore_stderr: true
    stdin: |
      set -u
      ref="unset_target"
      echo ${!ref}
      echo "should not print"

  - name: "Indirect expansion to set variable works"
    stdin: |
      set -u
      target="value"
      ref="target"
      echo ${!ref}

  # Case statements
  - name: "Unset variable in case pattern errors"
    ignore_stderr: true
    stdin: |
      set -u
      case "$unset_var" in
        *) echo "matched" ;;
      esac
      echo "should not print"

  - name: "Unset variable with default in case works"
    stdin: |
      set -u
      case "${unset_var:-default}" in
        default) echo "matched" ;;
      esac

  # For loops
  - name: "Unset variable in for loop errors"
    ignore_stderr: true
    stdin: |
      set -u
      for item in $unset_var; do
        echo "$item"
      done
      echo "should not print"

  - name: "Unset variable with default in for loop works"
    stdin: |
      set -u
      for item in ${unset_var:-a b c}; do
        echo "$item"
      done

  # While loops with unset variables
  - name: "Unset variable in while condition errors"
    ignore_stderr: true
    stdin: |
      set -u
      while [ "$unset_var" != "stop" ]; do
        echo "loop"
        break
      done
      echo "should not print"

  # Read command
  - name: "read into variable then access works"
    stdin: |
      set -u
      echo "value" | read my_var || true
      echo "${my_var:-default}"

  - name: "Variable unset before read then set works"
    stdin: |
      set -u
      echo "test" | {
        read input
        echo "$input"
      }

  # Compound assignments
  - name: "Associative array unset key with default"
    stdin: |
      set -u
      declare -A assoc
      echo "${assoc[key]:-default}"

  # Pipelines
  - name: "Unset variable with default in pipeline works"
    stdin: |
      set -u
      echo "${unset_var:-default}" | cat

  # Here documents and here strings
  - name: "Unset variable in here doc errors"
    ignore_stderr: true
    stdin: |
      set -u
      cat <<EOF
      $unset_var
      EOF
      echo "should not print"

  - name: "Unset variable with default in here doc works"
    stdin: |
      set -u
      cat <<EOF
      ${unset_var:-default}
      EOF

  # Edge cases
  - name: "Empty string is not unset"
    stdin: |
      set -u
      var=""
      echo "var is: '$var'"

  - name: "Null value vs unset"
    stdin: |
      set -u
      null=""
      echo "${null-default}"
      echo "${unset-default}"

  - name: "IFS unset behavior"
    stdin: |
      set -u
      unset IFS
      echo "ok"

  - name: "PATH unset would error"
    ignore_stderr: true
    stdin: |
      set -u
      saved_path="$PATH"
      unset PATH
      echo "$PATH"
      echo "should not print"

  # Combination with other options
  - name: "set -u with set -e"
    ignore_stderr: true
    stdin: |
      set -eu
      echo "$unset_var"
      echo "should not print"

  # Declare without assignment
  - name: "declare without value then access errors"
    ignore_stderr: true
    stdin: |
      set -u
      declare my_var
      echo "$my_var"
      echo "should not print"

  - name: "declare with value then access works"
    stdin: |
      set -u
      declare my_var="value"
      echo "$my_var"

  - name: "readonly without value then access errors"
    ignore_stderr: true
    stdin: |
      set -u
      readonly my_var
      echo "$my_var"
      echo "should not print"

  - name: "Nameref to set variable with set -u"
    known_failure: true
    stdin: |
      set -u
      target="value"
      declare -n ref=target
      echo "$ref"

  - name: "Nameref to unset variable with set -u errors"
    known_failure: true
    ignore_stderr: true
    stdin: |
      set -u
      declare -n ref=unset_target
      echo "$ref"
      echo "should not print"
