name: "Builtins: unset"
cases:
  - name: "Basic unset usage"
    stdin: |
      var=value
      unset var
      echo "var: ${var}"

  - name: "Unset multiple variables"
    stdin: |
      var1=value1
      var2=value2
      unset var1 var2
      echo "var1: ${var1}, var2: ${var2}"

  - name: "Unset function"
    ignore_stderr: true
    stdin: |
      function myfunc() {
        echo "Hello, world!"
      }
      unset myfunc
      myfunc

  - name: "Unset -f function"
    ignore_stderr: true
    stdin: |
      function myfunc() {
        echo "Hello, world!"
      }
      unset -f myfunc
      myfunc

  - name: "Unset indexed array element"
    stdin: |
      declare -a myarray=(a b c)

      unset myarray[0]
      declare -p myarray

      unset myarray[3]
      declare -p myarray

      unset myarray[2]
      declare -p myarray

      unset myarray[1]
      declare -p myarray

  - name: "Unset associative array element"
    stdin: |
      echo "[1]"

      declare -A myarray=([key]=value)

      unset myarray[key]
      declare -p myarray

      echo "[2]"

      declare -A myarray=([key]=value)

      unset "myarray[key]"
      declare -p myarray

      echo "[3]"

      declare -A myarray=([key]=value)
      key="x:y:z"

      unset "myarray[key]"
      declare -p myarray

  - name: "Unset array element with interesting expression"
    stdin: |
      declare -a myarray=(a b c d e)

      echo "Initial array:"
      declare -p myarray
      echo

      i=4
      unset myarray[i]
      echo "After removing element at index 4:"
      declare -p myarray
      echo

      unset myarray[6/2]
      echo "After removing element at index 3:"
      declare -p myarray
      echo

  - name: "Unset array element with negative index"
    stdin: |
      declare -a myarray=(a b c d e)

      echo "Initial array:"
      declare -p myarray
      echo

      unset "myarray[-1]"
      echo "After removing last element (index -1):"
      declare -p myarray
      echo

      unset "myarray[-1]"
      echo "After removing new last element (index -1 again):"
      declare -p myarray
      echo

      unset "myarray[-2]"
      echo "After removing second-to-last element (index -2):"
      declare -p myarray
      echo

  - name: "Unset array element with negative index out of bounds"
    ignore_stderr: true
    stdin: |
      declare -a myarray=(a b c)

      echo "Initial array:"
      declare -p myarray
      echo

      unset "myarray[-4]"
      echo "After attempting to remove with index -4 (out of bounds):"
      declare -p myarray
      echo "Return code: $?"

  - name: "Unset array element with variable negative index"
    stdin: |
      declare -a myarray=(10 20 30 40 50)

      echo "Initial array:"
      declare -p myarray
      echo

      i=-1
      unset "myarray[i]"
      echo "After removing with variable index i=-1:"
      declare -p myarray
      echo

      i=-2
      unset "myarray[i]"
      echo "After removing with variable index i=-2:"
      declare -p myarray
      echo

  - name: "Unset local in same function"
    stdin: |
      var="global"

      myfunc() {
        echo "In myfunc"
        local -i var="10"
        declare -p var
        unset var
        echo "After unset"
        declare -p var
        var="20"
      }

      echo "Before call: var=${var}"
      myfunc
      echo "After call: var=${var}"

  - name: "Unset locals in callers"
    stdin: |
      firstfunc() {
        local var="first"
        echo "entered firstfunc: var=${var}"
        secondfunc
        echo "leaving firstfunc: var=${var}"
      }

      secondfunc() {
        local var="second"
        echo "entered secondfunc: var=${var}"
        thirdfunc
        echo "leaving secondfunc: var=${var}"
      }

      thirdfunc() {
        echo "entered thirdfunc: var=${var}"
        unset -v var
        echo "after first unset: var=${var}"
        var+=":updated"
        echo "   ...and updated: var=${var}"
        unset -v var
        echo "after second unset: var=${var}"
        var+=":updated"
        echo "   ...and updated: var=${var}"
        unset -v var
        echo "after third unset: var=${var}"
        var+=":updated"
        echo "   ...and updated: var=${var}"
        echo "leaving firstfunc: var=${var}"
      }

      var="global"
      echo "before calls: var=${var}"
      firstfunc
      echo "after calls: var=${var}"

  - name: "Unset with nameref"
    known_failure: true
    stdin: |
      declare -n ref=var
      var="value"

      echo "[Before unset]"
      echo "ref: ${ref}"
      echo "var: ${var}"

      unset ref

      echo "[After unset]"
      echo "ref: ${ref}"
      echo "var: ${var}"

  - name: "Unset -n removes nameref itself"
    known_failure: true
    stdin: |
      target="value"
      declare -n ref=target
      echo "before: target=$target ref=$ref"
      unset -n ref
      echo "after unset -n: target=$target"
      declare -p ref 2>/dev/null || echo "ref is gone"
      declare -p target 2>/dev/null && echo "target still declared"

  - name: "Unset array element through nameref"
    known_failure: true
    stdin: |
      target=(a b c d e)
      declare -n ref=target
      unset 'ref[2]'
      declare -p target
      unset 'ref[0]'
      declare -p target

  - name: "Unset odd function names"
    stdin: |
      echo "[Checking existing]"
      type [

      echo "[Defining function]"
      function [() {
        :
      }

      echo "[Checking defined]"
      type [

      echo "[Unsetting function]"
      unset [
      echo "unset result: $?"

      echo "[Checking after unset]"
      type [
