#!/usr/bin/env bash

set -o nounset -o noglob +o braceexpand
shopt -s lastpipe
unset CDPATH TMOUT
declare -r -x LC_ALL='C.UTF-8'

work () {

  # Create an associative array compound assignment containing random-length
  # quoted arrays, unquoted scalars, and literals

  local -i array_count=0
  local -i scalar_count=0

  local script="
set -o nounset -o noglob +o braceexpand
shopt -s lastpipe
unset CDPATH TMOUT
declare -r -x LC_ALL='C.UTF-8'
"

  local under_test=''

  local assignment_contents=''

  while (( ( SRANDOM & 7 ) > 0 )) do

    local -i type_selector="$(( SRANDOM & 32767 ))"
    if (( type_selector < 10923 )) then
      assignment_contents+="${SRANDOM} "
    else
      local list=''
      local -i element_count
      for (( element_count = SRANDOM & 7; element_count > 0; --element_count )) do
        list+="${SRANDOM} "
      done
      if (( type_selector < 21845 )) then
        local array_name="array_$(( array_count++ ))"
        under_test+="${array_name}=( ${list})"$'\n'
	assignment_contents+="\"\${${array_name}[@]}\" "
      else
        local scalar_name="scalar_$(( scalar_count++ ))"
	under_test+="${scalar_name}='${list% }'"$'\n'
	assignment_contents+="\${${scalar_name}} "
      fi
    fi

  done
  
  under_test+="
declare -A assoc
assoc=( ${assignment_contents})
set -- ${assignment_contents% }"

script+="${under_test}"'
breakage="false"
if (( ( ( ${#} + 1 ) / 2 ) != ${#assoc[@]} )) then
  breakage="true"
fi
while [[ ${breakage} == "false" && ${#} -gt 1 ]] do
  if [[ ${assoc[${1}]} != ${2} ]] then
    breakage="true"
  fi
  shift 2
done
if [[ ${breakage} == "false" && ${#} -eq 1 && -n ${assoc[${1}]} ]] then
  breakage="true"
fi
[[ ${breakage} == "false" ]]
exit
'

  if ! ./bash -c "${script}"; then
    (( ++error_count ))
    printf '========\n'
    printf '%s\n' "${under_test}"
    printf '========\n'
  fi

}

exit_trap () {
  printf '%s\n' "${test_count} tests"
  printf '%s\n' "${error_count} errors"
}

trap exit_trap EXIT

printf 'CTRL-C to end test\n'

declare -i test_count=0
declare -i error_count=0

while true; do
  (( ++test_count ))
  printf '%s\r' "test ${test_count}"
  work
done
