diff options
author | Bryan Drewery <bryan@shatow.net> | 2018-02-07 01:24:42 +0300 |
---|---|---|
committer | Bryan Drewery <bryan@shatow.net> | 2018-02-17 05:13:45 +0300 |
commit | c2c8cf77a35993e8a9927a4ab8870423dbe84a66 (patch) | |
tree | 6e5b4869b8657ba011cca17967ed1de79fe8ceca /test | |
parent | b3bd7dc822a697ef5a1b876b69c0874dfb873ff3 (diff) |
Add mapfile
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 1 | ||||
-rw-r--r-- | test/mapfile.sh | 363 |
2 files changed, 364 insertions, 0 deletions
diff --git a/test/Makefile b/test/Makefile index 7a4d8cb7..45aff85f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,6 +6,7 @@ TESTS=\ locks.sh \ locks_critical_section.sh \ locks_critical_section_nested.sh \ + mapfile.sh \ port_var_fetch.sh \ read_file.sh \ relpath.sh \ diff --git a/test/mapfile.sh b/test/mapfile.sh new file mode 100644 index 00000000..a34373cb --- /dev/null +++ b/test/mapfile.sh @@ -0,0 +1,363 @@ +#! /bin/sh + +. common.sh +. ${SCRIPTPREFIX}/include/hash.sh +. ${SCRIPTPREFIX}/include/parallel.sh +. ${SCRIPTPREFIX}/include/util.sh + +LINES=20 + +cleanup() { + kill_jobs + if [ -n "${TMP}" ]; then + rm -rf "${TMP}" + unset TMP + fi + if [ -n "${TMP2}" ]; then + rm -rf "${TMP2}" + unset TMP2 + fi +} +trap cleanup EXIT + +writer() { + local stdout="$1" + local type="$2" + + case ${type} in + pipe) exec > "${stdout}" ;; + mapfile) + mapfile out "${stdout}" "we" + ;; + esac + n=0 + until [ $n -eq ${LINES} ]; do + case ${type} in + pipe) echo "${n}" ;; + mapfile) mapfile_write "${out}" "${n}" ;; + esac + n=$((n + 1)) + done + if [ "${type}" = "mapfile" ]; then + mapfile_close "${out}" + fi +} + +if mapfile_builtin; then +# Test pipes +{ + [ -f /nonexistent ] + assert_not 0 $? "/nonexistent should not exist" + mapfile foo "/nonexistent" 2>/dev/null + assert_not 0 $? "mapfile should fail on nonexistent file" + assert '' "${foo}" "mapfile should not return a handle on nonexistent file" + mapfile_close "random" 2>/dev/null + assert_not 0 $? "mapfile_close on unopened handle should not succeed" + + TMP=$(mktemp -ut mapfile) + mkfifo "${TMP}" + spawn_job writer "${TMP}" pipe + + mapfile handle1 "${TMP}" + assert 0 $? "mapfile handle1 should succeed" + assert_not '' "${handle1}" "mapfile handle1 should return a handle" + + TMP2=$(mktemp -ut mapfile) + mkfifo "${TMP2}" + spawn_job writer "${TMP2}" mapfile + + mapfile handle2 "${TMP2}" + assert 0 $? "mapfile handle2 should succeed" + assert_not '' "${handle2}" "mapfile handle2 should return a handle" + + n=0 + until [ $n -eq ${LINES} ]; do + mapfile_read "${handle1}" line + assert 0 $? "mapfile_read handle1 should succeed line $n" + assert "$n" "$line" "mapfile_read handle1 should match line $n" + + mapfile_read "${handle2}" line + assert 0 $? "mapfile_read handle2 should succeed line $n" + assert "$n" "$line" "mapfile_read handle2 should match line $n" + + n=$((n + 1)) + done + + mapfile_close "${handle1}" + assert 0 $? "mapfile_close handle1 should succeed" + + mapfile_close "${handle2}" + assert 0 $? "mapfile_close handle2 should succeed" + + unset line + mapfile_read "${handle1}" line 2>/dev/null + assert_not 0 $? "mapfile_read on a closed handle should not succeed" + assert '' "$line" "mapfile_read on a closed handle should not modify line" + + kill_jobs +} + +# Test normal files + +# First test that each handle has 1 file pointer; a read after a write should +# not return the written data. +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + mapfile file "${TMP}" "w+e" + assert 0 $? "mapfile to standard file should pass" + assert_not "" "${file}" "mapfile file should return handle" + + mapfile_write "${file}" "test 1 2 3" + assert 0 $? "mapfile_write to standard file should pass" + + line=random + mapfile_read "${file}" line + assert 1 $? "mapfile_read from standard file after writing should EOF" + assert "" "${line}" "mapfile_read should match (file pointer moving)" + + echo "blah" >> "${TMP}" + mapfile_read "${file}" line + assert 0 $? "mapfile_read from standard file after manual writing should pass" + assert "blah" "${line}" "mapfile_read should match 2" + + mapfile_close "${file}" +} + +# Now test read setting vars properly. +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + mapfile file_out "${TMP}" "we" + assert 0 $? "mapfile to standard file_out should pass" + assert_not "" "${file_out}" "mapfile file_out should return handle" + + mapfile file_in "${TMP}" "re" + assert 0 $? "mapfile to standard file_in should pass" + assert_not "" "${file_in}" "mapfile file_in should return handle" + + mapfile_write "${file_out}" "test 1 2 3" + assert 0 $? "mapfile_write to standard file_out should pass" + + mapfile_read "${file_in}" line + assert 0 $? "mapfile_read from standard file_in to 1 var should pass" + assert "test 1 2 3" "${line}" "mapfile_read should consume an entire line" + + mapfile_write "${file_out}" "test" + assert 0 $? "mapfile_write to standard file_out should pass" + mapfile_read "${file_in}" line + assert 0 $? "mapfile_read from standard file_in to 1 var should pass" + assert "test" "${line}" "mapfile_read should match line 1" + + # IFS= mode + mapfile_write "${file_out}" " test 1 2 3 " + assert 0 $? "mapfile_write to standard file_out should pass" + extra="blah" + IFS= mapfile_read "${file_in}" line extra + assert 0 $? "mapfile_read from standard file_in to 2 var should pass" + echo "line '${line}' extra '${extra}'" + assert " test 1 2 3 " "${line}" "mapfile_read IFS= should match line 2" + assert "" "${extra}" "mapfile_read IFS= should match extra 2" + + # IFS mode + mapfile_write "${file_out}" " test 1 2 3 " + assert 0 $? "mapfile_write to standard file_out should pass" + extra="blah" + mapfile_read "${file_in}" line extra + assert 0 $? "mapfile_read from standard file_in to 2.1 var should pass" + assert "test" "${line}" "mapfile_read should match line 2.1" + assert "1 2 3" "${extra}" "mapfile_read should match extra 2.1" + + mapfile_write "${file_out}" "test 1 2 3" + assert 0 $? "mapfile_write to standard file_out should pass" + mapfile_read "${file_in}" line one two + assert 0 $? "mapfile_read from standard file_in to 3 var should pass" + assert "test" "${line}" "mapfile_read should match line 3" + assert "1" "${one}" "mapfile_read should match one 3" + assert "2 3" "${two}" "mapfile_read should match two 3" + + mapfile_write "${file_out}" "test 1 2 3" + assert 0 $? "mapfile_write to standard file_out should pass" + mapfile_read "${file_in}" line one two three + assert 0 $? "mapfile_read from standard file_in to 4 var should pass" + assert "test" "${line}" "mapfile_read should match line 4" + assert "1" "${one}" "mapfile_read should match one 4" + assert "2" "${two}" "mapfile_read should match two 4" + assert "3" "${three}" "mapfile_read should match three 4" + + mapfile_write "${file_out}" "test 1a 2b 3c 4" + assert 0 $? "mapfile_write to standard file_out should pass" + nothing=nothing + in=in + here=here + mapfile_read "${file_in}" line one two three nothing in here + assert 0 $? "mapfile_read from standard file_in to 4+ var should pass" + assert "test" "${line}" "mapfile_read should match line 4+" + assert "1a" "${one}" "mapfile_read should match one 4+" + assert "2b" "${two}" "mapfile_read should match two 4+" + assert "3c" "${three}" "mapfile_read should match three 4+" + assert "4" "${nothing}" "mapfile_read should clear nothing 4+" + assert "" "${in}" "mapfile_read should clear in 4+" + assert "" "${here}" "mapfile_read should clear here 4+" +} +fi + +# Test mapfile_read_loop +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + jot 10 0 > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while mapfile_read_loop "${TMP}" n; do + assert "$i" "$n" "value should match 1 $i" + echo "${n}" + i=$((i + 1)) + done + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Test mapfile_read_loop_redir +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + jot 10 0 > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while mapfile_read_loop_redir n; do + assert "$i" "$n" "value should match 1 $i" + echo "${n}" + i=$((i + 1)) + done < "${TMP}" + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Test mapfile_read_loop_redir with multi vars in IFS= mode +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + i=0 + until [ ${i} -eq 10 ]; do + echo " ${i} $((i + 5)) " + i=$((i + 1)) + done > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while IFS= mapfile_read_loop_redir n y; do + echo "'${n}' '${y} '" + assert " $i $((i + 5)) " "$n" "value should match 2 $i" + assert '' "$y" 'value should match 2 for y - blank' + i=$((i + 1)) + done < "${TMP}" + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Test mapfile_read_loop_redir with multi vars in IFS mode +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + i=0 + until [ ${i} -eq 10 ]; do + echo " ${i} $((i + 5)) " + i=$((i + 1)) + done > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" + assert "$i" "$n" "value should match 3 $i" + assert "$((i + 5))" "$y" "value should match 3 $((i + 5))" + i=$((i + 1)) + done < "${TMP}" + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Piped mapfile_read_loop_redir +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + i=0 + until [ ${i} -eq 10 ]; do + echo " ${i} $((i + 5)) " + i=$((i + 1)) + done > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" + done < "${TMP}" | while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" + assert "'$i'" "$n" "value should match quoted 4 $i" + assert "'$((i + 5))'" "$y" "value should match quoted 4 $((i + 5))" + i=$((i + 1)) + done + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Piped mapfile_read_loop_redir +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + i=0 + until [ ${i} -eq 10 ]; do + echo " ${i} $((i + 5)) " + i=$((i + 1)) + done > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + cat "${TMP}" | while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" + done | while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" + assert "'$i'" "$n" "value should match quoted 5 $i" + assert "'$((i + 5))'" "$y" "value should match quoted 5 $((i + 5))" + i=$((i + 1)) + done + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} + +# Nested mapfile_read_loop_redir +# It's possible that a nested one will try to read from a parent's handle. +{ + rm -f "${TMP}" + TMP=$(mktemp -t mapfile) + + i=0 + until [ ${i} -eq 10 ]; do + echo " ${i} $((i + 5)) " + i=$((i + 1)) + done > "${TMP}" + + expectedfds=$(procstat -f $$|wc -l) + i=0 + while mapfile_read_loop_redir n y; do + echo "'${n}' '${y}'" | while mapfile_read_loop_redir m z; do + echo "'${m}' '${z}'" + done + done < "${TMP}" | while mapfile_read_loop_redir n y; do + assert "''$i''" "$n" "value should match double quoted 6 $i" + assert "''$((i + 5))''" "$y" "value should match double quoted 6 $((i + 5))" + i=$((i + 1)) + done + fds=$(procstat -f $$|wc -l) + assert "${expectedfds}" "${fds}" "fd leak" +} |