sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

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