296 lines
8.3 KiB
YAML
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
|