tst-iconv_prog-buffer.sh 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #!/bin/bash
  2. # Test for iconv (the program) buffer management.
  3. # Copyright (C) 2024-2026 Free Software Foundation, Inc.
  4. # This file is part of the GNU C Library.
  5. # The GNU C Library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Lesser General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2.1 of the License, or (at your option) any later version.
  9. # The GNU C Library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. # You should have received a copy of the GNU Lesser General Public
  14. # License along with the GNU C Library; if not, see
  15. # <https://www.gnu.org/licenses/>.
  16. # Arguments:
  17. # root of the build tree ($(objpfx-common))
  18. # test command wrapper (for running on the board/with new ld.so)
  19. # extra flags to pass to iconv
  20. # number of times to double the input files in size (default: 0)
  21. exec 2>&1
  22. set -e
  23. exec {logfd}>&1
  24. codir=$1
  25. test_program_prefix="$2"
  26. # Use internal converters to avoid issues with module loading.
  27. iconv_args="-f ASCII -t UTF-8 $3"
  28. file_size_doublings=${4-0}
  29. failure=false
  30. tmp=`mktemp -d`
  31. trap 'rm -rf "$tmp"' 0
  32. echo ABC > "$tmp/abc"
  33. echo DEF > "$tmp/def"
  34. echo GGG > "$tmp/ggg"
  35. echo HH > "$tmp/hh"
  36. echo XY > "$tmp/xy"
  37. echo ZT > "$tmp/zt"
  38. echo OUT > "$tmp/out-template"
  39. : > "$tmp/empty"
  40. printf '\xff' > "$tmp/0xff"
  41. # Length should be a prime number, to help with buffer alignment testing.
  42. printf '\xc3\xa4\xe2\x80\x94\xe2\x80\x94\xc3\xa4\n' > "$tmp/utf8-sequence"
  43. # Double all files to produce larger buffers.
  44. for p in "$tmp"/* ; do
  45. i=0
  46. while test $i -lt $file_size_doublings; do
  47. cat "$p" "$p" > "$tmp/scratch"
  48. mv "$tmp/scratch" "$p"
  49. i=$(($i + 1))
  50. done
  51. done
  52. cat "$tmp/xy" "$tmp/0xff" "$tmp/zt" > "$tmp/0xff-wrapped"
  53. run_iconv () {
  54. local c=0
  55. if test "${FUNCNAME[2]}" = main; then
  56. c=1
  57. fi
  58. echo "${BASH_SOURCE[$c]}:${BASH_LINENO[$c]}: iconv $iconv_args $@" >&$logfd
  59. $test_program_prefix $codir/iconv/iconv_prog $iconv_args "$@"
  60. }
  61. check_out_expected () {
  62. if test -x "$tmp/out" ; then
  63. echo "error: iconv output file is executable"
  64. failure=true
  65. fi
  66. if ! cmp -s "$tmp/out" "$tmp/expected" ; then
  67. echo "error: iconv output difference" >&$logfd
  68. echo "*** expected ***" >&$logfd
  69. cat "$tmp/expected" >&$logfd
  70. echo "*** actual ***" >&$logfd
  71. cat "$tmp/out" >&$logfd
  72. failure=true
  73. fi
  74. }
  75. expect_files () {
  76. local f
  77. ! test -z "$1"
  78. cp "$tmp/$1" "$tmp/expected"
  79. shift
  80. for f in "$@" ; do
  81. cat "$tmp/$f" >> "$tmp/expected"
  82. done
  83. check_out_expected
  84. }
  85. check_out () {
  86. cat > "$tmp/expected"
  87. check_out_expected
  88. }
  89. expect_exit () {
  90. local expected=$1
  91. shift
  92. # Prevent failure for stopping the script.
  93. if "$@" ; then
  94. actual=$?
  95. else
  96. actual=$?
  97. fi
  98. if test "$actual" -ne "$expected"; then
  99. echo "error: expected exit status $expected, not $actual" >&$logfd
  100. exit 1
  101. fi
  102. }
  103. ignore_failure () {
  104. set +e
  105. "$@"
  106. status=$?
  107. set -e
  108. }
  109. # Concatenation test.
  110. run_iconv -o "$tmp/out" "$tmp/abc" "$tmp/def"
  111. expect_files abc def
  112. # Single-file in-place conversion.
  113. run_iconv -o "$tmp/out" "$tmp/out"
  114. expect_files abc def
  115. # Multiple input files with in-place conversion.
  116. run_iconv -o "$tmp/out" "$tmp/out" "$tmp/abc"
  117. expect_files abc def abc
  118. run_iconv -o "$tmp/out" "$tmp/ggg" "$tmp/out"
  119. expect_files ggg abc def abc
  120. run_iconv -o "$tmp/out" "$tmp/hh" "$tmp/out" "$tmp/hh"
  121. expect_files hh ggg abc def abc hh
  122. cp "$tmp/out-template" "$tmp/out"
  123. run_iconv -o "$tmp/out" "$tmp/ggg" "$tmp/out" "$tmp/out" "$tmp/ggg"
  124. expect_files ggg out-template out-template ggg
  125. cp "$tmp/out-template" "$tmp/out"
  126. run_iconv -o "$tmp/out" "$tmp/ggg" "$tmp/out" "$tmp/hh" "$tmp/out" "$tmp/ggg"
  127. expect_files ggg out-template hh out-template ggg
  128. # Empty output should truncate the output file if exists.
  129. cp "$tmp/out-template" "$tmp/out"
  130. run_iconv -o "$tmp/out" </dev/null
  131. expect_files empty
  132. cp "$tmp/out-template" "$tmp/out"
  133. run_iconv -o "$tmp/out" - </dev/null
  134. expect_files empty
  135. cp "$tmp/out-template" "$tmp/out"
  136. run_iconv -o "$tmp/out" /dev/null
  137. expect_files empty
  138. cp "$tmp/out-template" "$tmp/out"
  139. expect_exit 1 run_iconv -c -o "$tmp/out" "$tmp/0xff"
  140. expect_files empty
  141. # But not if we are writing to standard output.
  142. cp "$tmp/out-template" "$tmp/out"
  143. run_iconv </dev/null >>"$tmp/out"
  144. expect_files out-template
  145. cp "$tmp/out-template" "$tmp/out"
  146. run_iconv - </dev/null >>"$tmp/out"
  147. expect_files out-template
  148. cp "$tmp/out-template" "$tmp/out"
  149. run_iconv /dev/null >>"$tmp/out"
  150. expect_files out-template
  151. # Conversion errors should avoid clobbering an existing file if
  152. # it is also an input file.
  153. cp "$tmp/0xff" "$tmp/out"
  154. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/out"
  155. expect_files 0xff
  156. cp "$tmp/0xff" "$tmp/out"
  157. expect_exit 1 run_iconv -o "$tmp/out" < "$tmp/out"
  158. expect_files 0xff
  159. cp "$tmp/0xff" "$tmp/out"
  160. expect_exit 1 run_iconv -o "$tmp/out" - < "$tmp/out"
  161. expect_files 0xff
  162. cp "$tmp/0xff-wrapped" "$tmp/out"
  163. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/out"
  164. expect_files 0xff-wrapped
  165. cp "$tmp/0xff-wrapped" "$tmp/out"
  166. expect_exit 1 run_iconv -o "$tmp/out" < "$tmp/out"
  167. expect_files 0xff-wrapped
  168. cp "$tmp/0xff-wrapped" "$tmp/out"
  169. expect_exit 1 run_iconv -o "$tmp/out" - < "$tmp/out"
  170. expect_files 0xff-wrapped
  171. cp "$tmp/0xff-wrapped" "$tmp/out"
  172. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/abc" "$tmp/out"
  173. expect_files 0xff-wrapped
  174. cp "$tmp/0xff-wrapped" "$tmp/out"
  175. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/abc" - < "$tmp/out"
  176. expect_files 0xff-wrapped
  177. # If errors are ignored, the file should be overwritten.
  178. cp "$tmp/0xff-wrapped" "$tmp/out"
  179. expect_exit 1 run_iconv -c -o "$tmp/out" "$tmp/out"
  180. expect_files xy zt
  181. cp "$tmp/0xff" "$tmp/out"
  182. expect_exit 1 run_iconv -c -o "$tmp/out" "$tmp/abc" "$tmp/out" "$tmp/def"
  183. expect_files abc def
  184. cp "$tmp/out-template" "$tmp/out"
  185. expect_exit 1 \
  186. run_iconv -c -o "$tmp/out" "$tmp/abc" "$tmp/0xff" "$tmp/def" 2>"$tmp/err"
  187. ! test -s "$tmp/err"
  188. expect_files abc def
  189. cp "$tmp/out-template" "$tmp/out"
  190. expect_exit 1 run_iconv -c -o "$tmp/out" \
  191. "$tmp/abc" "$tmp/0xff-wrapped" "$tmp/def" 2>"$tmp/err"
  192. ! test -s "$tmp/err"
  193. expect_files abc xy zt def
  194. cp "$tmp/0xff-wrapped" "$tmp/out"
  195. expect_exit 1 run_iconv -c -o "$tmp/out" "$tmp/out" "$tmp/abc" "$tmp/out" "$tmp/def"
  196. expect_files xy zt abc xy zt def
  197. cp "$tmp/0xff-wrapped" "$tmp/out"
  198. expect_exit 1 run_iconv -o "$tmp/out" \
  199. "$tmp/out" "$tmp/abc" "$tmp/out" "$tmp/def"
  200. expect_files 0xff-wrapped
  201. cp "$tmp/0xff-wrapped" "$tmp/out"
  202. expect_exit 1 run_iconv -c -o "$tmp/out" \
  203. "$tmp/abc" "$tmp/out" "$tmp/def" "$tmp/out"
  204. expect_files abc xy zt def xy zt
  205. # If the file does not exist yet, it should not be created on error.
  206. rm "$tmp/out"
  207. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/0xff"
  208. ! test -e "$tmp/out"
  209. expect_exit 1 run_iconv -o "$tmp/out" < "$tmp/0xff"
  210. ! test -e "$tmp/out"
  211. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/abc" "$tmp/0xff" "$tmp/def"
  212. ! test -e "$tmp/out"
  213. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/abc" - < "$tmp/0xff" "$tmp/def"
  214. ! test -e "$tmp/out"
  215. # Listing standard input multiple times should not fail (bug 32050).
  216. run_iconv -o "$tmp/out" "$tmp/xy" - - "$tmp/zt" < "$tmp/abc"
  217. expect_files xy abc zt
  218. # NB: Extra iconv args are ignored after this point. Actual
  219. # multi-byte conversion does not work with tiny buffers.
  220. iconv_args="-f UTF-8 -t ASCII"
  221. printf 'x\n\xc3' > "$tmp/incomplete"
  222. expect_exit 1 run_iconv -o "$tmp/out" "$tmp/incomplete"
  223. check_out <<EOF
  224. x
  225. EOF
  226. # Test buffering behavior if the buffer ends with an incomplete
  227. # multi-byte sequence.
  228. prefix=""
  229. prefix_length=0
  230. while test $prefix_length -lt 12; do
  231. echo "info: testing prefix length $prefix_length" 2>&$logfd
  232. printf "%s" "$prefix" > "$tmp/prefix"
  233. cat "$tmp/prefix" "$tmp/utf8-sequence" > "$tmp/tmp"
  234. iconv_args="-f UTF-8 -t UCS-4"
  235. run_iconv -o "$tmp/out1" "$tmp/tmp"
  236. iconv_args="-f UCS-4 -t UTF-8"
  237. run_iconv -o "$tmp/out" "$tmp/out1"
  238. expect_files prefix utf8-sequence
  239. prefix="$prefix@"
  240. prefix_length=$(($prefix_length + 1))
  241. done
  242. if $failure ; then
  243. exit 1
  244. fi