test-bash.sh (14192B)
1 # -*- mode: sh; mode: sh-bash -*- 2 3 ble-import lib/core-test 4 5 ble/test/start-section 'bash' 49 6 7 # case $word を quote する必要がある条件は? 8 9 # 当然 bash の文法的に特別な意味がある文字を直接記述する時は quote が必要。word 10 # splitting 及び pathname expansions は発生しない。$* や ${arr[*]} が含まれる場 11 # 合は quote していてもしていなくても要素が IFS で連結されるので IFS には注意が 12 # 必要。 13 ( 14 # word splitting does not happen 15 a='x y' 16 ble/test code:'ret=$a' ret="x y" 17 ble/test '[[ $a == "x y" ]]' 18 ble/test 'case $a in ("x y") true ;; (*) false ;; esac' 19 a='x y' 20 ble/test code:'ret=$a' ret="x y" 21 ble/test '[[ $a == "x y" ]]' 22 ble/test 'case $a in ("x y") true ;; (*) false ;; esac' 23 IFS=abc a='xabcy' 24 ble/test code:'ret=$a' ret="xabcy" 25 ble/test '[[ $a == "xabcy" ]]' 26 ble/test 'case $a in ("xabcy") true ;; (*) false ;; esac' 27 IFS=$' \t\n' 28 29 # BUG bash-3.0..4.3 30 # word splitting happens in here strings. 31 a='x y' 32 ble/test 'read -r ret <<< $a' ret="x y" 33 a='x y' 34 if ((_ble_bash<40400)); then 35 ble/test 'read -r ret <<< $a' ret="x y" 36 else 37 ble/test 'read -r ret <<< $a' ret="x y" 38 fi 39 IFS=abc a='xabcy' 40 if ((_ble_bash<40400)); then 41 ble/test 'read -r ret <<< $a' ret="x y" 42 else 43 ble/test 'read -r ret <<< $a' ret="xabcy" 44 fi 45 IFS=$' \t\n' 46 47 # pathname expansion does not happen 48 b='/*' 49 ble/test code:'ret=$b' ret="/*" 50 ble/test 'case $b in ("/*") true ;; (*) false ;; esac' 51 ble/test 'read -r ret <<< $b' ret="/*" 52 ) 53 54 # Variable bugs 55 ( 56 # BUG bash-3.1 57 # a=(""); echo "a${a[*]}b" | cat -A とするとa^?b となって謎の文字が入る。 58 # echo "a""${a[*]}""b" 等とすれば大丈夫。 59 a=("") 60 function f1 { ret=$1; } 61 if ((30100<=_ble_bash&&_ble_bash<30200)); then 62 ble/test 'f1 "a${a[*]}b"' ret=$'a\177b' 63 ble/test code:'ret="a${a[*]}b"' ret=$'a\177b' 64 ble/test 'case "a${a[*]}b" in ($'\''a\177b'\'') true ;; (*) false ;; esac' 65 ble/test 'read -r ret <<< "a${a[*]}b"' ret=$'a\177b' 66 else 67 ble/test 'f1 "a${a[*]}b"' ret='ab' 68 ble/test code:'ret="a${a[*]}b"' ret='ab' 69 ble/test 'case "a${a[*]}b" in (ab) true ;; (*) false ;; esac' 70 ble/test 'read -r ret <<< "a${a[*]}b"' ret=ab 71 fi 72 73 # BUG bash-3.0..3.1 74 # "${var//%d/123}" は動かない。"${var//'%d'/123}" 等とすればOK。 75 var=X%dX%dX 76 if ((_ble_bash<30200)); then 77 ble/test code:'ret=${var//%d/.}' ret='X%dX%dX' 78 else 79 ble/test code:'ret=${var//%d/.}' ret='X.X.X' 80 fi 81 82 # BUG bash-3.0..3.1 83 # local GLOBIGNORE すると、関数を出てもパス名展開の時にその影響が残っている。 84 # (直接変数の中身を見ても何もない様に見えるが。) unset GLOBIGNORE などとす 85 # ると直る。 86 ble/test/chdir 87 touch {a..c}.txt 88 function f1 { local GLOBIGNORE='*.txt'; } 89 if ((_ble_bash<30200)); then 90 ble/test 'f1; echo *' stdout='*' 91 else 92 ble/test 'f1; echo *' stdout='a.txt b.txt c.txt' 93 fi 94 95 # BUG bash-3.0 96 # ${#param} は文字数ではなくバイト数を返す、という事になっているらしいが、 97 # 実際に試してみると文字数になっている (bash-3.0.22)。何処かで patch が当たっ 98 # たのだろうか → これは bash-3.0.4 で修正された様だ。 99 # 100 # (※${param:ofs:len} は 3.0-beta1 以降であれば文字数でカウントされる) 101 if ((_ble_bash<30004)); then 102 ble/test code:'a=あ ret=${#a}' ret=3 103 else 104 ble/test code:'a=あ ret=${#a}' ret=1 105 fi 106 107 # BUG bash-3.0 108 # declare -p A で改行を含む変数を出力すると改行が消える。例: 一見正しく出力 109 # されている様に錯覚するが "\ + 改行" は改行のエスケープではなく、長い文字 110 # 列リテラルを二行に書く為の記法である。つまり、無視される。 111 # 112 # $ A=$'\n'; declare -p A 113 # | A="\ 114 # | " 115 builtin unset -v v 116 v=$'a\nb' 117 if ((_ble_bash<30100)); then 118 ble/test code:'declare -p v' stdout=$'declare -- v="a\\\nb"' 119 elif ((_ble_bash<50200)); then 120 ble/test code:'declare -p v' stdout=$'declare -- v="a\nb"' 121 else 122 ble/test code:'declare -p v' stdout='declare -- v=$'\''a\nb'\' 123 fi 124 125 # BUG bash-3.0 [Ref #D1774] 126 # "${...#$'...'}" (#D1774) という形を使うと $'...' の展開結果が ... ではな 127 # く '...' の様に、余分な引用符が入ってしまう。extquote を設定しても結果は 128 # 変わらない。 129 builtin unset -v scalar 130 if ((_ble_bash<30100)); then 131 ble/test code:'ret="[${scalar-$'\''hello'\''}]"' ret="['hello']" # disable=#D1774 132 else 133 ble/test code:'ret="[${scalar-$'\''hello'\''}]"' ret='[hello]' # disable=#D1774 134 fi 135 ) 136 137 # Array bugs 138 ( 139 # BUG bash-4.0..4.4 [Ref #D0924] 140 # ローカルで local -a x; local -A x とすると segfault する。 141 # ref http://lists.gnu.org/archive/html/bug-bash/2019-02/msg00047.html, 142 # f() { local -a a; local -A a; }; f # これで segfault する 143 # 144 # - 別のスコープで定義された配列を -A とした場合には起こらない。 145 # - 同じスコープの場合でも unset a してから local -A a すれば大丈夫。 146 # - グローバルでは起こらない。 147 function f1 { local -a a; local -A a; } 148 if ((_ble_bash<40000)); then 149 ble/test f1 exit=2 150 elif ((_ble_bash<50000)); then 151 ble/test '(f1)' exit=139 # SIGSEGV 152 else 153 ble/test f1 exit=1 154 fi 155 156 # BUG bash-3.0..4.4 157 # 配列要素または $* を case 単語もしくは here strings で連結する時 IFS が " 158 # " に置き換わる。 159 c=(a b c) 160 IFS=x 161 if ((_ble_bash<50000)); then 162 # bash-3.0..4.4 bug 163 ble/test 'case ${c[*]} in ("a b c") true ;; (*) false ;; esac' 164 ble/test 'read -r ret <<< ${c[*]}' ret="a b c" 165 else 166 ble/test 'case ${c[*]} in ("axbxc") true ;; (*) false ;; esac' 167 ble/test 'read -r ret <<< ${c[*]}' ret="axbxc" 168 fi 169 ble/test 'case "${c[*]}" in ("axbxc") true ;; (*) false ;; esac' 170 ble/test 'read -r ret <<< "${c[*]}"' ret="axbxc" 171 IFS=$' \t\n' 172 173 # BUG bash-3.0..4.2 174 # 配列要素を代入右辺で連結する時 IFS が " " に置き換わる。 175 # 動く例: 176 # IFS= eval 'value=${arr[*]}' 177 # IFS= eval 'value="${arr[*]}"' 178 # IFS= eval 'local value="${arr[*]}"' 179 # 動かない例 (間に空白が入ってしまう): 180 # IFS= eval 'local value=${arr[*]}' 181 c=(a b c) 182 ble/test code:'ret=${c[*]}' ret="a b c" 183 ble/test 'case ${c[*]} in ("a b c") true ;; (*) false ;; esac' 184 ble/test 'read -r ret <<< ${c[*]}' ret="a b c" 185 # ${c[*]} is affected by IFS 186 IFS=x 187 if ((_ble_bash<40300)); then 188 # bash-3.0..4.2 bug 189 ble/test code:'ret=${c[*]}' ret="a b c" 190 else 191 ble/test code:'ret=${c[*]}' ret="axbxc" 192 fi 193 ble/test code:'ret="${c[*]}"' ret="axbxc" 194 IFS=$' \t\n' 195 196 # BUG bash-3.0..4.1 197 # 宣言されているが unset の変数について ${#a[*]} が 1 を返す。 198 # a[${#a[*}]=value もしくは ble/array#push a value するとき、その配列を事前 199 # に宣言したければ local -a a のように -a を指定する必要がある。 200 # 201 # [問題] 202 # 203 # bash-4.0, 4.1 (local): bash-4.1 以下で関数内で local arr しただけで 204 # ${#arr[*]} が 1 になる。その後、要素 #1 を設定しても ${#arr[*]} は 1 のま 205 # まである。これの所為で arr[${#arr[*]}]=... としても常に要素 #1 にしか代入 206 # されない事になる。 207 # 208 # bash-3.0 ~ 3.2 (declare): bash-3.2 以下では関数内に限らず declare arr し 209 # ただけで ${#arr[*]} が 1 になる。但し、要素[1] に設定をすると ${#arr[*]} 210 # は 2 に増加する。従って余分な空要素があるものの ble/array#push は失敗しな 211 # い。 212 # 213 # [解決] 214 # 215 # local -a arr とすれば問題は起きない。※local arr=() (#D0184) としても問題 216 # は起きないがこの記述だと今度は bash-3.0 で文字列 '()' が代入されて問題で 217 # ある。 218 builtin unset -v arr1 arr2 219 local arr1 220 local -a arr2 221 if ((_ble_bash<40200)); then 222 ble/test code:'ret=${#arr1[@]}' ret=1 223 else 224 ble/test code:'ret=${#arr1[@]}' ret=0 225 fi 226 ble/test code:'ret=${#arr2[@]}' ret=0 227 228 # BUG bash-3.0..3.2 [Ref #D1241] 229 # ^? や ^A の値が declare -p で ^A^? や ^A^A に変換されてしまう。 230 a=($'\x7F' $'\x01') 231 if ((_ble_bash<40000)); then 232 ble/test 'declare -p a' stdout=$'declare -a a=\'([0]="\x01\x01\x01\x7F" [1]="\x01\x01\x01\x01")\'' # ' 233 elif ((_ble_bash<40400)); then 234 ble/test 'declare -p a' stdout=$'declare -a a=\'([0]="\x01\x7F" [1]="\x01\x01")\'' # ' 235 else 236 ble/test 'declare -p a' stdout='declare -a a=([0]=$'\''\177'\'' [1]=$'\''\001'\'')' # disable=#D0525 237 fi 238 239 # BUG bash-3.1 240 # 呼出先の関数で、呼出元で定義されているのと同名の配列を作っても、中が空になる。 241 # > $ function dbg/test2 { local -a hello=(1 2 3); echo "hello=(${hello[*]})";} 242 # > $ function dbg/test1 { local -a hello=(3 2 1); dbg/test2;} 243 # > $ dbg/test1 244 # > hello=() 245 # 246 # これは bash-3.1-patches/bash31-004 で修正されている様だ。 247 function f1 { local -a arr=(b b b); ble/util/print "(${arr[*]})"; } 248 function f2 { local -a arr=(a a a); f1; } 249 if ((30100<=_ble_bash&&_ble_bash<30104)); then 250 ble/test f2 stdout='()' 251 else 252 ble/test f2 stdout='(b b b)' 253 fi 254 255 # BUG bash-3.1 256 # そもそも bash-3.1 は function a { local -a alpha=() beta=(); } を parse 257 # できないので ble.sh のテストを起動するのもままならない。 258 if ((30100<=_ble_bash&&_ble_bash<30104)); then 259 ble/test 'function f1 { local -a alpha=(); local -a beta=(); }' 260 else 261 ble/test 'function f1 { local -a alpha=() beta=(); }' 262 fi 263 264 # BUG bash-3.0..3.1 [Ref #D0182] 265 # ${#arr[n]} が文字数ではなくバイト数を返す 266 if ((_ble_bash<30200)); then 267 ble/test code:'ret=あ ret=${#ret[0]}' ret=3 # disable=#D0182 268 else 269 ble/test code:'ret=あ ret=${#ret[0]}' ret=1 # disable=#D0182 270 fi 271 272 # BUG bash-3.0 [Ref #D0184] 273 # local a=(...) や declare a=(...) (#D0184) とすると、a="(...)" と同じ事に 274 # なる。a=() の形式ならば問題ない。 275 declare ret=(1 2 3) # disable=#D0184 276 if ((_ble_bash<30100)); then 277 ble/test ret='(1 2 3)' 278 else 279 ble/test ret='1' 280 fi 281 282 # BUG bash-3.0 [Ref #D0525] 283 # 今まで local -a a=() の形式ならば問題ないと信じてきたが、どうやらlocal -a 284 # a=('1 2') (#D0525) が local -a a=(1 2) と同じ意味になってしまうようだ。 285 # a="123 345"; declare -a arr=("$a"); (#D0525) このようにしても駄目だ。 286 # a="123 345"; declare -a arr; arr=("$a"); こうする必要がある。 287 declare -a ret=("1 2") # disable=#D0525 288 if ((_ble_bash<30100)); then 289 ble/test ret='1' 290 else 291 ble/test ret='1 2' 292 fi 293 v="1 2 3" 294 declare -a ret=("$v") # disable=#D0525 295 if ((_ble_bash<30100)); then 296 ble/test ret='1' 297 else 298 ble/test ret='1 2 3' 299 fi 300 301 # BUG bash-3.0 [Ref #D1570] 302 # * "${var[@]/xxx/yyy}" (#D1570) はスカラー変数に対して空の結果を生む。 303 # ${var[@]//xxx/yyy}, ${var[@]/%/yyy}, ${var[@]/#/yyy} (#D1570) について 304 # も同様である。 305 # * "${scalar[@]/xxxx}" (#D1570) は全て空になる。変数名が配列である事が保証 306 # されている必要がある。 307 builtin unset -v scalar 308 scalar=abcd 309 if ((_ble_bash<30100)); then 310 ble/test code:'ret=${scalar[@]//[bc]}' ret='' # disable=#D1570 311 elif ((40300<=_ble_bash&&_ble_bash<40400)); then 312 ble/test code:'ret=${scalar[@]//[bc]}' ret=$'\001a\001\001\001d' # disable=#D1570 313 else 314 ble/test code:'ret=${scalar[@]//[bc]}' ret='ad' # disable=#D1570 315 fi 316 ) 317 318 # Other bugs 319 ( 320 # BUG bash-3.0..4.0 (3.0..5.2 in 非対話セッション) 321 322 # $'' 内に \' を入れていると履歴展開が '' の中で起こる? 例えば 323 # rex='a'$'\'\'''!a' とすると !a の部分が展開される (9f0644470 OK)。 324 # 325 # 因みに対応する履歴がない場合には 4.1 以下でエラーメッセージが表示される。 326 # 327 # Note: bash -c や独立したスクリプト実行の中だと 3.0..5.2 および devel の全バー 328 # ジョンで問題は再現する。対話セッションや set +H を指定した場合には問題は 329 # 3.0..4.0 でしか発生しない。 330 # 331 # Note: 遡ってみるとこの項目は memo.txt に commit 9f064447 (2015-03-08) で追 332 # 加されている。但し対応する項目は memo.txt には記述されていない。#D0206 が近 333 # いが微妙に異なることを議論している。 334 # 335 q=\' line='$'$q'\'$q'!!'$q'\'$q 336 ble/util/assign ret '(builtin history -s histentry; builtin history -p "$line")' 337 if ((_ble_bash<30100)); then 338 # 3.0 ではそもそも失敗する。 339 ble/test code:'' ret= 340 elif ((_ble_bash<40100)) || [[ $- != *[iH]* ]]; then 341 # 非対話セッション または 3.1..4.0 では意図せず展開が起こる 342 ble/test code:'' ret="${line//!!/histentry}" 343 else 344 # 期待した振る舞い 345 ble/test code:'' ret="$line" 346 fi 347 ble/test '(builtin history -c; builtin history -p "$line")' stdout= 348 349 # BUG bash-3.0 [Ref #D1956] 350 # 関数定義の一番外側でリダイレクトしてもリダイレクトされない。例えば、 351 # function func { ls -l /proc/$BASHPID/fd/{0..2}; } <&"$fd0" >&"$fd1" 352 # 353 # どうも更に関数を func REDIRECT & で呼び出した時にのみ発生する様だ。呼び出 354 # し元のリダイレクションリストで上書きされているという事だろうか。e 355 function f1 { ble/util/print hello; } >&"$fd1" 356 function f2 { ble/util/print hello >&"$fd1"; } 357 function f3 { { ble/util/print hello; } >&"$fd1"; } 358 function test1 { 359 local fd1= 360 ble/fd#alloc fd1 '>&1' 361 "$1" >/dev/null & local pid=$! 362 wait "$pid" 363 ble/fd#close fd1 364 } 365 if ((_ble_bash<30100)); then 366 ble/test 'test1 f1' stdout= 367 else 368 ble/test 'test1 f1' stdout=hello 369 fi 370 ble/test 'test1 f2' stdout=hello 371 ble/test 'test1 f3' stdout=hello 372 ) 373 374 ble/test/end-section