name: "Arrays"
incompatible_configs: ["sh"]
common_test_files:
  - path: "helpers.sh"
    contents: |
      stable_print_assoc_array() {
          # TODO(nameref): enable use of nameref when implemented; for now
          # we assume the name of the array is assoc_array
          # local -n assoc_array=$1
          local key

          for key in $(printf "%s\n" "${!assoc_array[@]}" | sort -n); do
              echo "\"${key}\" => ${assoc_array[${key}]}"
          done
      }
cases:
  - name: "Basic indexed array definition and access"
    stdin: |
      var=(a b c)
      echo "var: $var"
      echo "var: ${var}"
      echo "var[0]: ${var[0]}"
      echo "var[1]: ${var[1]}"
      echo "var[2]: ${var[2]}"
      echo "var[3]: ${var[3]}"
      echo "var[4]: ${var[4]}"
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Negative indexed array access"
    stdin: |
      var=(a b c)
      echo "var[-1]: ${var[-1]}"
      echo "var[-2]: ${var[-2]}"
      echo "var[-3]: ${var[-3]}"

  - name: "Too large negative indexed array access"
    ignore_stderr: true
    stdin: |
      var=(a b c)
      echo "var[-4]: ${var[-4]}"

  - name: "Negative indexed array access (set)"
    stdin: |
      var=(a b c d e f g)
      var[-1]=x
      var[-3]=z
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Too large negative indexed array access (set)"
    ignore_stderr: true
    stdin: |
      var=(a b c)
      var[-4]=x
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Define array with expansion"
    stdin: |
      body='a b'

      var=($body)
      declare -p var

      declare -a var2=($body)
      declare -p var2

  - name: "Arrays with empty values"
    stdin: |
      var1=(a "" c)
      declare -p var1

      var2=(a "$nonexistent" c)
      declare -p var2

      var3=("" "" "")
      declare -p var3

  - name: "Basic associative array definition and access"
    stdin: |
      declare -A var=([0]=99 [a]=3 [b]=4 [c]=5)
      echo "var: $var"
      echo "var: ${var}"
      echo "var[0]: ${var[0]}"
      echo "var[a]: ${var[a]}"
      echo "var[b]: ${var[b]}"
      echo "var[c]: ${var[c]}"
      echo "var[d]: ${var[d]}"

      key="a"
      echo "var[key]: ${var[${key}]}"

  - name: "Array updating via index"
    stdin: |
      var=(a b c)
      var[1]="d"
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Array index assignment"
    stdin: |
      x=(3 2 1)
      y[${x[0]}]=10
      y[x[1]]=11
      declare -p y

  - name: "Replacing array with string"
    stdin: |
      var=(a b c)
      var="x"
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Array replacing"
    stdin: |
      var=(a b c)
      var=(d e f)
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Appending array to indexed array"
    stdin: |
      var=(a b c)
      var+=(e f g)
      echo "var[*]: ${var[*]}"
      declare -p var

      var+=("" "" "")
      declare -p var

      var+=(h "i" "$nonexistent" j)
      var+=(j k l)
      declare -p var

  - name: "Appending array to declared-but-unset indexed array"
    stdin: |
      declare -a var
      var+=(e f g)
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Appending item to indexed array"
    stdin: |
      var=(a b c)
      var+=d
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Appending item to element of indexed array"
    stdin: |
      declare -a var=(1 2 3)
      var[1]+=2
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Appending item to element of int indexed array"
    stdin: |
      declare -ai var=(1 2 3)
      var[1]+=2
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Appending items to int indexed array"
    stdin: |
      declare -ai var=(1 2 3)
      var+=(4 value 6)
      declare -p var

  - name: "Appending array to associative array"
    stdin: |
      source helpers.sh
      declare -A assoc_array=([a]=1 [b]=2 [c]=3)
      assoc_array+=([d]=4 [e]=5 [f]=6)
      stable_print_assoc_array assoc_array

  - name: "Appending array to declared-but-unset associative array"
    stdin: |
      source helpers.sh
      declare -A assoc_array
      assoc_array+=([d]=4 [e]=5 [f]=6)
      stable_print_assoc_array assoc_array

  - name: "Appending item to associative array"
    stdin: |
      source helpers.sh
      declare -A assoc_array=([a]=1 [b]=2 [c]=3)
      assoc_array+=d
      stable_print_assoc_array assoc_array

  - name: "Appending item to element of associative array"
    stdin: |
      source helpers.sh
      declare -A assoc_array=([a]=1 [b]=2 [c]=3)
      assoc_array[b]+=2
      stable_print_assoc_array assoc_array

  - name: "Appending item to element of int associative array"
    stdin: |
      source helpers.sh
      declare -Ai assoc_array=([a]=1 [b]=2 [c]=3)
      assoc_array[b]+=2
      stable_print_assoc_array assoc_array

  - name: "Appending items to int associative array"
    stdin: |
      source helpers.sh
      declare -Ai assoc_array=([a]=1 [b]=2 [c]=3)
      assoc_array+=([d]=4 [e]=value [f]=6)
      stable_print_assoc_array assoc_array

  - name: "Appending array to item"
    stdin: |
      var=x
      var+=(a b c)
      echo "var[*]: ${var[*]}"
      declare -p var

  - name: "Fill associative array"
    stdin: |
      declare -Ag myarray

      myfunc() {
          local myarg=$1 element
          shift
          for element in "$@"; do
              echo "Setting: myarray[$element]=$myarg"
              myarray[$element]="${myarg}${element}"
          done
      }

      myfunc 'first' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat

  - name: "Declare via array index"
    stdin: |
      declare -A assoc_array["key"]="value"
      declare -p assoc_array

      declare -a indexed_array[5]="value"
      declare -p indexed_array

      declare implicit_array[5]="value"
      declare -p implicit_array

      declare -A no_value_assoc_array["key"]
      declare -p no_value_assoc_array

      declare no_value_indexed_array[33]
      declare -p no_value_indexed_array

  - name: "Create array via index update"
    stdin: |
      i=0
      my_array[i++]="c"
      echo "0: i=$i array=${my_array[@]}"
      my_array[i++]="b"
      echo "1: i=$i array=${my_array[@]}"
      my_array[i++]="a"
      echo "2: i=$i array=${my_array[@]}"

  - name: "Expansion of array body"
    stdin: |
      elements="a b c"

      array1=(${elements})
      declare -p array1

      array2=("${elements}")
      declare -p array2

  - name: "Copy array"
    stdin: |
      src=(a b c)

      dest1=("${src[*]}")
      declare -p dest1

      dest2=(${src[*]})
      declare -p dest2

      dest3=("${src[@]}")
      declare -p dest3

      dest4=(${src[@]})
      declare -p dest4

  - name: "Multi-line definition of array"
    stdin: |
      array=(
          a
          b
          c
      )
      declare -p array

  - name: "Dump values from non-existent array"
    stdin: |
      for key in ${NONEXISTENT[@]}; do
        echo "@-Key: ${key}"
      done
      for key in "${NONEXISTENT[@]}"; do
        echo "@-Quoted Key: ${key}"
      done

      for key in ${NONEXISTENT[*]}; do
        echo "*-Key: ${key}"
      done
      for key in "${NONEXISTENT[*]}"; do
        echo "*-Quoted Key: ${key}"
      done

  - name: "Use non-existent var in indexed array index"
    stdin: |
      declare -a myarray=(10)
      echo "Value: ${myarray[$non_existent_var]}"

  - name: "Use non-existent var in associative array index"
    ignore_stderr: true
    stdin: |
      declare -A myarray=([0]="default" ["a"]="other")
      echo "Value: ${myarray[$non_existent_var]}"

  - name: "Nested array reference"
    stdin: |
      x=(2 3 4)
      echo ${x[${x[0]}]}

  - name: "Append array-resulting expansion to array"
    stdin: |
      declare -a otherarray=("a" "b" "c")
      declare -a ourarray=()

      ourarray+=("${otherarray[@]/a/x}")
      declare -p otherarray
      declare -p ourarray

  - name: "Array declaration in a function"
    stdin: |
      outer() {
        inner=()
        if test true; then
          echo true
        else
          echo false
        fi
      }

      outer

  - name: "Array element expansion with non-standard IFS"
    stdin: |
      IFS='|'

      declare -a myarray=(abc 1 f)
      echo "\"\${myarray[@]}\": ${myarray[@]}"
      echo "\"\${myarray[*]}\": ${myarray[*]}"
      echo "\${myarray[@]}:" ${myarray[@]}
      echo "\${myarray[*]}:" ${myarray[*]}

  - name: "Empty array with newline"
    stdin: |
      declare -a myarray=(
      )
