Files
sausage/userland/brush/source/brush-shell/tests/cases/compat/builtins/mapfile.yaml
T
2026-11-11 22:04:16 +00:00

296 lines
8.3 KiB
YAML

name: "Builtins: mapfile"
cases:
#
# Basic functionality
#
- name: "mapfile basic"
stdin: |
mapfile arr < <(echo -e "a\nb\nc")
declare -p arr
- name: "mapfile -t"
stdin: |
mapfile -t arr < <(echo -e "a\nb\nc")
declare -p arr
- name: "readarray -t"
stdin: |
readarray -t arr < <(echo -e "a\nb\nc")
declare -p arr
- name: "mapfile default MAPFILE"
stdin: |
mapfile -t < <(echo -e "a\nb")
declare -p MAPFILE
#
# -O flag
#
- name: "mapfile -O starts at offset"
stdin: |
mapfile -t -O 3 arr < <(echo -e "a\nb\nc")
declare -p arr
- name: "mapfile -O 0 preserves existing"
stdin: |
arr=(x y z w)
mapfile -t -O 0 arr < <(echo -e "a\nb")
declare -p arr
- name: "mapfile without -O clears existing"
stdin: |
arr=(x y z w)
mapfile -t arr < <(echo -e "a\nb")
declare -p arr
- name: "mapfile -O preserves sparse array"
stdin: |
declare -a arr
arr[0]=x
arr[5]=y
arr[10]=z
mapfile -t -O 2 arr < <(echo -e "a\nb")
declare -p arr
- name: "mapfile -O large offset"
stdin: |
mapfile -t -O 100 arr < <(echo -e "a\nb")
declare -p arr
- name: "mapfile -O negative"
ignore_stderr: true
stdin: |
mapfile -O -1 arr < /dev/null
echo "exit: $?"
#
# Variable state edge cases
#
- name: "mapfile into nonexistent variable"
stdin: |
mapfile -t newvar < <(echo -e "a\nb")
declare -p newvar
- name: "mapfile into string variable"
stdin: |
myvar="hello"
mapfile -t myvar < <(echo -e "a\nb")
declare -p myvar
- name: "mapfile -O into string variable"
stdin: |
myvar="hello"
mapfile -t -O 2 myvar < <(echo -e "a\nb")
declare -p myvar
- name: "mapfile into associative array"
ignore_stderr: true
stdin: |
declare -A myassoc
mapfile -t myassoc < <(echo -e "a\nb")
echo "exit: $?"
#
# -d delimiter
#
- name: "mapfile -d custom delimiter"
stdin: |
mapfile -t -d 'Z' arr < <(echo -ne "helloZthereZgeneralZkenobi")
declare -p arr
- name: "mapfile -d empty string (NUL)"
stdin: |
mapfile -t -d '' arr < <(printf 'a\0b\0c')
declare -p arr
#
# -n count
#
- name: "mapfile -n limits count"
stdin: |
mapfile -t -n 2 arr < <(echo -e "a\nb\nc\nd")
declare -p arr
- name: "mapfile -n 0 no limit"
stdin: |
mapfile -t -n 0 arr < <(echo -e "a\nb\nc")
declare -p arr
#
# -s skip
#
- name: "mapfile -s"
stdin: |
mapfile -t -s 2 arr < <(echo -e "a\nb\nc\nd")
declare -p arr
- name: "mapfile -s with -n"
stdin: |
mapfile -t -s 1 -n 2 arr < <(echo -e "a\nb\nc\nd\ne")
declare -p arr
#
# -u file descriptor
#
- name: "mapfile -u reads from fd"
stdin: |
exec 3< <(echo -e "a\nb\nc")
mapfile -t -u 3 arr
exec 3<&-
declare -p arr
- name: "mapfile -u invalid fd"
ignore_stderr: true
stdin: |
exec 99<&- # fd 99 must be closed, but the harness can leak one in
mapfile -u 99 arr
echo "exit: $?"
#
# Combinations
#
- name: "mapfile -O with -s and -n"
stdin: |
mapfile -t -O 10 -s 1 -n 2 arr < <(echo -e "a\nb\nc\nd\ne")
declare -p arr
- name: "mapfile multiple invocations without -O"
stdin: |
mapfile -t arr < <(echo -e "a\nb")
mapfile -t arr < <(echo -e "x\ny\nz")
declare -p arr
- name: "mapfile multiple invocations with -O"
stdin: |
mapfile -t arr < <(echo -e "a\nb")
mapfile -t -O 2 arr < <(echo -e "x\ny\nz")
declare -p arr
#
# Empty input
#
- name: "mapfile empty input"
stdin: |
mapfile -t arr < /dev/null
declare -p arr 2>/dev/null || echo "arr not set"
- name: "mapfile empty input clears existing"
stdin: |
arr=(x y z)
mapfile -t arr < /dev/null
declare -p arr 2>/dev/null || echo "arr not set"
- name: "mapfile -O empty input preserves"
stdin: |
arr=(x y z)
mapfile -t -O 0 arr < /dev/null
declare -p arr
- name: "mapfile into nameref variable"
known_failure: true
stdin: |
declare -a target
declare -n ref=target
mapfile -t ref < <(echo -e "a\nb\nc")
declare -p target
- name: "mapfile -O into nameref variable"
known_failure: true
stdin: |
target=(x y)
declare -n ref=target
mapfile -t -O 2 ref < <(echo -e "a\nb")
declare -p target
# Sent by another program, so that it reaches the shell through the kernel; nothing is ever
# written to the FIFO, so the read ends only if the signal ends it.
- name: "A signal that ends the shell ends a mapfile waiting for input"
known_failure: true # TODO(signals): signals aren't delivered to the shell
timeout_in_seconds: 5
stdin: |
mkfifo p; exec 3<>p
trap 'echo exit-trap' EXIT
( sleep 0.2; /bin/kill -TERM $$ ) &
mapfile -t -n 1 a <&3
echo "not reached"
#
# Option parsing
#
- name: "mapfile options given more than once keep the last"
stdin: |
mapfile -t -n 1 -n 2 arr <<< $'a\nb\nc'; declare -p arr
mapfile -t -s 1 -s 0 arr <<< $'a\nb'; declare -p arr
arr=(x y z); mapfile -t -O 2 -O 1 arr <<< $'a\nb'; declare -p arr
mapfile -t -d , -d . arr <<< 'a.b,c'; declare -p arr
- name: "mapfile with combined and attached short options"
stdin: |
mapfile -tn2 arr <<< $'a\nb\nc'; declare -p arr
mapfile -td, arr <<< 'a,b'; declare -p arr
mapfile -t -u3 arr 3<<< $'a\nb'; declare -p arr
arr=(x y z); mapfile -t -O+1 arr <<< $'a\nb'; declare -p arr
mapfile -t -n +2 arr <<< $'a\nb\nc'; declare -p arr
mapfile -t -d - arr <<< 'a-b'; declare -p arr
- name: "mapfile with -- before the array name"
stdin: |
mapfile -t -- arr <<< $'a\nb'; declare -p arr
- name: "mapfile with an unknown option or missing value fails with status 2"
ignore_stderr: true
stdin: |
mapfile -Z arr <<< a; echo "rc=$?"
mapfile -t -O; echo "rc=$?"
- name: "mapfile with an invalid count fails with status 1"
known_failure: true # TODO(mapfile): fails with status 2
ignore_stderr: true
stdin: |
mapfile -t -n abc arr <<< a; echo "rc=$?"
mapfile -t -n -1 arr <<< a; echo "rc=$?"
mapfile -t -s -1 arr <<< a; echo "rc=$?"
mapfile -t -s abc arr <<< a; echo "rc=$?"
mapfile -t -O abc arr <<< a; echo "rc=$?"
mapfile -t -c 0 arr <<< a; echo "rc=$?"
mapfile -t -c abc arr <<< a; echo "rc=$?"
mapfile -t -u -1 arr <<< a; echo "rc=$?"
- name: "mapfile checks every count, origin and descriptor it is given"
ignore_stderr: true
stdin: |
# Only whether it fails is compared: the status itself is a known failure.
exec 99<&- # fd 99 must be closed, but the harness can leak one in
arr=(keep); mapfile -t -s-1 -s0 arr <<< data; echo "failed=$(($? != 0)) ${arr[*]}"
arr=(keep); mapfile -t -c0 -c5000 arr <<< data; echo "failed=$(($? != 0)) ${arr[*]}"
arr=(keep); mapfile -t -n-1 -n1 arr <<< data; echo "failed=$(($? != 0)) ${arr[*]}"
arr=(keep); mapfile -t -O-1 -O0 arr <<< data; echo "failed=$(($? != 0)) ${arr[*]}"
arr=(keep); mapfile -t -u 99 -u 0 arr <<< data; echo "failed=$(($? != 0)) ${arr[*]}"
arr=(keep); mapfile -t -s0 -s1 arr <<< $'a\nb'; echo "failed=$(($? != 0)) ${arr[*]}"
- name: "mapfile -C calls back for each group of lines"
known_failure: true # TODO(mapfile): -C and -c are not implemented
stdin: |
cb() { echo "cb $*"; }
mapfile -t -C cb -c 1 arr <<< $'a\nb'; declare -p arr
- name: "mapfile ignores words after the array name"
known_failure: true # TODO(mapfile): an extra word is an error, and later options are parsed
ignore_stderr: true
stdin: |
mapfile -t arr extra <<< a; echo "rc=$?"
mapfile -t arr -n 1 <<< $'a\nb'; declare -p arr
- name: "mapfile into an invalid name fails"
known_failure: true # TODO(mapfile): an invalid name is accepted
ignore_stderr: true
stdin: |
mapfile -t 1bad <<< a; echo "rc=$?"
mapfile -t -- -x <<< a; echo "rc=$?"
- name: "mapfile option values may begin with a hyphen"
known_failure: true # TODO(mapfile): such a value is taken for an option
stdin: |
mapfile -t -d -- arr <<< 'a--b'; declare -p arr
mapfile -t -s -0 arr <<< $'a\nb'; declare -p arr