sistema_progs

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

test-util.sh (74531B)


      1 # source script for ble.sh interactive sessions -*- mode: sh; mode: sh-bash -*-
      2 
      3 ble-import lib/core-test
      4 
      5 ble/test/start-section 'ble/util' 1234
      6 
      7 # bleopt
      8 
      9 (
     10   # 定義・設定・出力
     11   ble/test 'bleopt a=1' \
     12            exit=2
     13   ble/test 'bleopt a' \
     14            stdout= exit=2
     15   ble/test 'bleopt a:=2'
     16   ble/test 'bleopt a' \
     17            stdout="bleopt a=2"
     18   ble/test '[[ $bleopt_a == 2 ]]'
     19   ble/test "bleopt | grep 'bleopt a='" \
     20            stdout="bleopt a=2"
     21   ble/test 'bleopt a=3'
     22   ble/test 'bleopt a' \
     23            stdout="bleopt a=3"
     24 
     25   # setter
     26   function bleopt/check:a { value=123; }
     27   ble/test 'bleopt a=4 && bleopt a'
     28   stdout="bleopt a=123"
     29   function bleopt/check:a { false; }
     30   ble/test 'bleopt a=5' \
     31            exit=1
     32   ble/test 'bleopt a' \
     33            stdout="bleopt a=123"
     34 
     35   # 複数引数
     36   ble/test bleopt f:=10 g:=11
     37   ble/test bleopt f g \
     38            stdout="bleopt f=10${_ble_term_nl}bleopt g=11"
     39   ble/test bleopt f=12 g=13
     40   ble/test bleopt f g \
     41            stdout="bleopt f=12${_ble_term_nl}bleopt g=13"
     42 
     43   # bleopt/declare
     44   ble/test bleopt/declare -v b 6
     45   ble/test bleopt b stdout="bleopt b=6"
     46   ble/test bleopt/declare -n c 7
     47   ble/test bleopt c stdout="bleopt c=7"
     48   ble/test bleopt d:= e:=
     49   ble/test bleopt/declare -v d 8
     50   ble/test bleopt/declare -n e 9
     51   ble/test bleopt d stdout="bleopt d="
     52   ble/test bleopt e stdout="bleopt e=9"
     53 )
     54 
     55 # ToDo
     56 # bleopt/expand-variable-pattern
     57 # bleopt/reinitialize
     58 
     59 # ble/test
     60 
     61 ble/test ble/util/setexit 0   exit=0
     62 ble/test ble/util/setexit 1   exit=1
     63 ble/test ble/util/setexit 9   exit=9
     64 ble/test ble/util/setexit 128 exit=128
     65 ble/test ble/util/setexit 255 exit=255
     66 
     67 # ble/unlocal
     68 
     69 (
     70   a=1
     71   function f1 {
     72     ble/util/print "g:$a"
     73     local a=2
     74     ble/util/print "l:$a"
     75     ble/util/unlocal a
     76     ble/util/print "g:$a"
     77     a=3
     78   }
     79   ble/test 'f1; ble/util/print "g:$a"' \
     80            stdout=g:1 \
     81            stdout=l:2 \
     82            stdout=g:1 \
     83            stdout=g:3
     84 
     85   function f2 {
     86     ble/util/print "f1:$a@f2"
     87     local a=3
     88     ble/util/print "f2:$a@f2"
     89     ble/util/unlocal a
     90     ble/util/print "f1:$a@f2"
     91     a=$a+
     92   }
     93   function f1 {
     94     ble/util/print "g:$a@f1"
     95     local a=2
     96     ble/util/print "f1:$a@f1"
     97     f2
     98     ble/util/print "f1:$a@f1"
     99     ble/util/unlocal a
    100     ble/util/print "g:$a@f1"
    101     a=$a+
    102   }
    103   ble/test 'a=1; f1; ble/util/print "g:$a@g"' \
    104            stdout=g:1@f1 \
    105            stdout=f1:2@f1 \
    106            stdout=f1:2@f2 \
    107            stdout=f2:3@f2 \
    108            stdout=f1:2@f2 \
    109            stdout=f1:2+@f1 \
    110            stdout=g:1@f1 \
    111            stdout=g:1+@g
    112 )
    113 
    114 # ble/util/upvar, ble/util/uparr (Freddy Vulto's trick)
    115 
    116 (
    117   function f1 {
    118     local a=1 b=2
    119     local result=$((a+b))
    120     local "$1" && ble/util/upvar "$1" "$result"
    121   }
    122   ble/test 'f1 x; ret=$x' ret=3
    123   ble/test 'f1 a; ret=$a' ret=3
    124   ble/test 'f1 result; ret=$result' ret=3
    125 
    126   function f2 {
    127     local a=1
    128     local -a b=(2)
    129     local -a result; result=("$((a+b[0]))" y z)
    130     local "$1" && ble/util/uparr "$1" "${result[@]}"
    131   }
    132   ble/test 'f2 x; ret="(${x[*]})"' ret='(3 y z)'
    133   ble/test 'f2 a; ret="(${a[*]})"' ret='(3 y z)'
    134   ble/test 'f2 b; ret="(${b[*]})"' ret='(3 y z)'
    135   ble/test 'f2 result; ret="(${result[*]})"' ret='(3 y z)'
    136 )
    137 
    138 # ble/util/save-vars, restore-vars
    139 
    140 (
    141   varnames=(name x y count data)
    142 
    143   function print-status {
    144     ble/util/print "name=$name x=$x y=$y count=$count data=(${data[*]})"
    145   }
    146 
    147   function f1 {
    148     local "${varnames[@]/%/=}" # WA #D1570 checked
    149 
    150     name=1 x=2 y=3 count=4 data=(aa bb cc dd)
    151     print-status
    152     ble/util/save-vars save1_ "${varnames[@]}"
    153 
    154     name=one x= y=A count=1 data=(Q)
    155     print-status
    156     ble/util/save-vars save2_ "${varnames[@]}"
    157 
    158     ble/util/restore-vars save1_ "${varnames[@]}"
    159     print-status
    160 
    161     ble/util/restore-vars save2_ "${varnames[@]}"
    162     print-status
    163   }
    164   ble/test f1 \
    165            stdout='name=1 x=2 y=3 count=4 data=(aa bb cc dd)' \
    166            stdout='name=one x= y=A count=1 data=(Q)' \
    167            stdout='name=1 x=2 y=3 count=4 data=(aa bb cc dd)' \
    168            stdout='name=one x= y=A count=1 data=(Q)'
    169 )
    170 
    171 # ble/variable#get-attr
    172 
    173 (
    174   declare v=1
    175   declare -i i=1
    176   export x=2
    177   builtin readonly r=3
    178   declare -a a=()
    179   if ((_ble_bash>=40000)); then
    180     declare -A A=()
    181     declare -u u=a
    182     declare -l l=B
    183     declare -c c=c
    184   fi
    185   if ((_ble_bash>=40300)); then
    186     declare -n n=r
    187   fi
    188 
    189   ble/test 'ble/variable#get-attr v; ret=$attr' ret=
    190   ble/test 'ble/variable#get-attr i; ret=$attr' ret=i
    191   ble/test 'ble/variable#get-attr x; ret=$attr' ret=x
    192   ble/test 'ble/variable#get-attr r; ret=$attr' ret=r
    193   ble/test 'ble/variable#get-attr a; ret=$attr' ret=a
    194   if ((_ble_bash>=40000)); then
    195     ble/test 'ble/variable#get-attr u; ret=$attr' ret=u
    196     ble/test 'ble/variable#get-attr l; ret=$attr' ret=l
    197     ble/test 'ble/variable#get-attr c; ret=$attr' ret=c
    198     ble/test 'ble/variable#get-attr A; ret=$attr' ret=A
    199   fi
    200   # ((_ble_bash>=40300)) &&
    201   #   ble/test 'ble/variable#get-attr n; ret=$attr' ret=n
    202 
    203   ble/test 'ble/variable#has-attr i i'
    204   ble/test 'ble/variable#has-attr x x'
    205   ble/test 'ble/variable#has-attr r r'
    206   ble/test 'ble/variable#has-attr a a'
    207   ble/test 'ble/variable#has-attr v i' exit=1
    208   ble/test 'ble/variable#has-attr v x' exit=1
    209   ble/test 'ble/variable#has-attr v r' exit=1
    210   ble/test 'ble/variable#has-attr v a' exit=1
    211   if ((_ble_bash>=40000)); then
    212     ble/test 'ble/variable#has-attr u u'
    213     ble/test 'ble/variable#has-attr l l'
    214     ble/test 'ble/variable#has-attr c c'
    215     ble/test 'ble/variable#has-attr A A'
    216     ble/test 'ble/variable#has-attr v u' exit=1
    217     ble/test 'ble/variable#has-attr v l' exit=1
    218     ble/test 'ble/variable#has-attr v c' exit=1
    219     ble/test 'ble/variable#has-attr v A' exit=1
    220   fi
    221   # if ((_ble_bash>=40300)); then
    222   #   ble/test 'ble/variable#has-attr n n'
    223   #   ble/test 'ble/variable#has-attr v n' exit=1
    224   # fi
    225 
    226   ble/test 'ble/is-inttype i'
    227   ble/test 'ble/is-inttype v' exit=1
    228   ble/test 'ble/is-readonly r'
    229   ble/test 'ble/is-readonly v' exit=1
    230   if ((_ble_bash>=40000)); then
    231     ble/test 'ble/is-transformed u'
    232     ble/test 'ble/is-transformed l'
    233     ble/test 'ble/is-transformed c'
    234     ble/test 'ble/is-transformed v' exit=1
    235   fi
    236 )
    237 
    238 # ble/variable#is-global
    239 function is-global { (builtin readonly "$1"; ! local "$1" 2>/dev/null); }
    240 (
    241   v1=1 v2=2
    242   ((_ble_bash>=40200)) &&
    243     declare -g v1u v2u
    244   function f1 {
    245     local v2=22 v3=33
    246     local v2u v3u
    247     f2
    248   }
    249   function f2 {
    250     local v4=444 v4u
    251     ble/test 'is-global v0'
    252     ble/test 'is-global v1'
    253     ble/test 'is-global v2' exit=1
    254     ble/test 'is-global v3' exit=1
    255     ble/test 'is-global v4' exit=1
    256 
    257     ble/test 'ble/variable#is-global v0'
    258     ble/test 'ble/variable#is-global v1'
    259     ble/test 'ble/variable#is-global v2' exit=1
    260     ble/test 'ble/variable#is-global v3' exit=1
    261     ble/test 'ble/variable#is-global v4' exit=1
    262 
    263     ble/test 'ble/variable#is-global v0u'
    264     if ((_ble_bash>=40200)); then
    265       ble/test 'ble/variable#is-global v1u'
    266       ble/test 'ble/variable#is-global v2u' exit=1
    267     fi
    268     ble/test 'ble/variable#is-global v3u' exit=1
    269     ble/test 'ble/variable#is-global v4u' exit=1
    270   }
    271   f1
    272 )
    273 
    274 # ToDo
    275 # ble/variable#copy-state
    276 
    277 # _ble_array_prototype
    278 (
    279   _ble_array_prototype=()
    280   ble/test 'echo "${#_ble_array_prototype[@]}"' stdout=0
    281   ble/array#reserve-prototype 10
    282   ble/test 'echo "${#_ble_array_prototype[@]}"' stdout=10
    283   ble/test 'x=("${_ble_array_prototype[@]::10}"); echo "${#x[@]}"' stdout=10
    284   ble/array#reserve-prototype 3
    285   ble/test 'echo "${#_ble_array_prototype[@]}"' stdout=10
    286   ble/test 'x=("${_ble_array_prototype[@]::3}"); echo "${#x[@]}"' stdout=3
    287 )
    288 
    289 # ble/is-{array,assoc}
    290 (
    291   declare -a a=()
    292   declare b=
    293   ble/test 'ble/is-array a'
    294   ble/test 'ble/is-array b' exit=1
    295   ble/test 'ble/is-array c' exit=1
    296 
    297   if ((_ble_bash>=40000)); then
    298     declare -A A=()
    299     ble/test 'ble/is-array A' exit=1
    300     ble/test 'ble/is-assoc a' exit=1
    301     ble/test 'ble/is-assoc A'
    302     ble/test 'ble/is-assoc b' exit=1
    303     ble/test 'ble/is-assoc c' exit=1
    304   fi
    305 )
    306 
    307 # ble/array#set
    308 (
    309   ble/test 'ble/array#set a; echo "${#a[@]}:(${a[*]})"' stdout='0:()'
    310   ble/test 'ble/array#set a Q; echo "${#a[@]}:(${a[*]})"' stdout='1:(Q)'
    311   ble/test 'ble/array#set a 1 2 3; echo "${#a[@]}:(${a[*]})"' stdout='3:(1 2 3)'
    312   ble/test 'ble/array#set a; echo "${#a[@]}:(${a[*]})"' stdout='0:()'
    313 )
    314 
    315 # ble/array#push
    316 (
    317   declare -a a=()
    318   ble/array#push a
    319   ble/test 'echo "${#a[@]}:(${a[*]})"' stdout='0:()'
    320   ble/array#push a A
    321   ble/test 'echo "${#a[@]}:(${a[*]})"' stdout='1:(A)'
    322   ble/array#push a B C
    323   ble/test 'echo "${#a[@]}:(${a[*]})"' stdout='3:(A B C)'
    324   ble/array#push a
    325   ble/test 'echo "${#a[@]}:(${a[*]})"' stdout='3:(A B C)'
    326 )
    327 
    328 # ble/array#pop
    329 (
    330   function result { ble/util/print "$ret:${#arr[*]}:(${arr[*]})"; }
    331   ble/test 'arr=()     ; ble/array#pop arr; result' stdout=':0:()'
    332   ble/test 'arr=(1)    ; ble/array#pop arr; result' stdout='1:0:()'
    333   ble/test 'arr=(1 2)  ; ble/array#pop arr; result' stdout='2:1:(1)'
    334   ble/test 'arr=(0 0 0); ble/array#pop arr; result' stdout='0:2:(0 0)'
    335   ble/test 'arr=(1 2 3); ble/array#pop arr; result' stdout='3:2:(1 2)'
    336   ble/test 'arr=(" a a " " b b " " c c "); ble/array#pop arr; result' \
    337            stdout=' c c :2:( a a   b b )'
    338 )
    339 
    340 # ble/array#unshift
    341 (
    342   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    343   a=()
    344   ble/array#unshift a
    345   ble/test status stdout='0:()'
    346   ble/array#unshift a A
    347   ble/test status stdout='1:(A)'
    348   ble/array#unshift a
    349   ble/test status stdout='1:(A)'
    350   ble/array#unshift a B
    351   ble/test status stdout='2:(B A)'
    352   ble/array#unshift a C D E
    353   ble/test status stdout='5:(C D E B A)'
    354   a=()
    355   ble/array#unshift a A B
    356   ble/test status stdout='2:(A B)'
    357 )
    358 
    359 # ble/array#reverse
    360 (
    361   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    362   a=(); ble/array#reverse a
    363   ble/test status stdout='0:()'
    364   a=(1); ble/array#reverse a
    365   ble/test status stdout='1:(1)'
    366   a=(xy zw); ble/array#reverse a
    367   ble/test status stdout='2:(zw xy)'
    368   a=(a 3 x); ble/array#reverse a
    369   ble/test status stdout='3:(x 3 a)'
    370   a=({1..10}) b=({10..1}); ble/array#reverse a
    371   ble/test status stdout="10:(${b[*]})"
    372   a=({1..9}) b=({9..1}); ble/array#reverse a
    373   ble/test status stdout="9:(${b[*]})"
    374 )
    375 
    376 # ble/array#insert-at
    377 (
    378   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    379   a=(); ble/array#insert-at a 0 A B C
    380   ble/test status stdout='3:(A B C)'
    381   a=(); ble/array#insert-at a 1 A B C
    382   ble/test status stdout='3:(A B C)'
    383   a=(x y z); ble/array#insert-at a 0 A
    384   ble/test status stdout='4:(A x y z)'
    385   a=(x y z); ble/array#insert-at a 1 A
    386   ble/test status stdout='4:(x A y z)'
    387   a=(x y z); ble/array#insert-at a 3 A
    388   ble/test status stdout='4:(x y z A)'
    389   a=(x y z); ble/array#insert-at a 0 A B C
    390   ble/test status stdout='6:(A B C x y z)'
    391   a=(x y z); ble/array#insert-at a 1 A B C
    392   ble/test status stdout='6:(x A B C y z)'
    393   a=(x y z); ble/array#insert-at a 3 A B C
    394   ble/test status stdout='6:(x y z A B C)'
    395   a=(x y z); ble/array#insert-at a 0
    396   ble/test status stdout='3:(x y z)'
    397   a=(x y z); ble/array#insert-at a 1
    398   ble/test status stdout='3:(x y z)'
    399   a=(x y z); ble/array#insert-at a 3
    400   ble/test status stdout='3:(x y z)'
    401 )
    402 
    403 # ble/array#insert-after
    404 (
    405   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    406   a=(hello world hello world)
    407   ble/array#insert-after a hello 1 2 3
    408   ble/test status stdout='7:(hello 1 2 3 world hello world)'
    409   a=(heart world hello world)
    410   ble/array#insert-after a hello 1 2 3
    411   ble/test status stdout='7:(heart world hello 1 2 3 world)'
    412   a=(hello world hello world)
    413   ble/test 'ble/array#insert-after a check 1 2 3' exit=1
    414   ble/test status stdout='4:(hello world hello world)'
    415 )
    416 
    417 # ble/array#insert-before
    418 (
    419   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    420   a=(hello world this)
    421   ble/array#insert-before a this with check
    422   ble/test status stdout='5:(hello world with check this)'
    423   a=(hello world this)
    424   ble/test 'ble/array#insert-before a haystack kick check' exit=1
    425   ble/test status stdout='3:(hello world this)'
    426 )
    427 
    428 # ble/array#remove
    429 (
    430   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    431   a=(xxx yyy xxx yyy yyy xxx fdsa fdsa)
    432   ble/array#remove a xxx
    433   ble/test status stdout='5:(yyy yyy yyy fdsa fdsa)'
    434   a=(aa aa aa aa aa)
    435   ble/array#remove a bb
    436   ble/test status stdout='5:(aa aa aa aa aa)'
    437   ble/array#remove a aa
    438   ble/test status stdout='0:()'
    439   ble/array#remove a cc
    440   ble/test status stdout='0:()'
    441 )
    442 
    443 # ble/array#index
    444 (
    445   a=(hello world this hello world)
    446   ble/test 'ble/array#index a hello' ret=0
    447   a=(world hep this hello world)
    448   ble/test 'ble/array#index a hello' ret=3
    449   a=(hello world this hello world)
    450   ble/test 'ble/array#index a check' ret=-1
    451 )
    452 
    453 # ble/array#last-index
    454 (
    455   a=(hello world this hello world)
    456   ble/test 'ble/array#last-index a hello' ret=3
    457   a=(world hep this hello world)
    458   ble/test 'ble/array#last-index a hello' ret=3
    459   a=(hello world this hello world)
    460   ble/test 'ble/array#last-index a check' ret=-1
    461 )
    462 
    463 # ble/array#remove-at
    464 (
    465   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    466   a=()
    467   ble/test 'ble/array#remove-at a 0; status' stdout='0:()'
    468   ble/test 'ble/array#remove-at a 10; status' stdout='0:()'
    469   a=(x y z)
    470   ble/test 'ble/array#remove-at a 4; status' stdout='3:(x y z)'
    471   ble/test 'ble/array#remove-at a 3; status' stdout='3:(x y z)'
    472   ble/test 'ble/array#remove-at a 1; status' stdout='2:(x z)'
    473   ble/test 'ble/array#remove-at a 0; status' stdout='1:(z)'
    474   ble/test 'ble/array#remove-at a 0; status' stdout='0:()'
    475   a=({a..z}) a1=({a..y}) a2=({b..y}) a3=({b..h} {j..y})
    476   ble/test 'ble/array#remove-at a 25; status' stdout="25:(${a1[*]})"
    477   ble/test 'ble/array#remove-at a 0; status' stdout="24:(${a2[*]})"
    478   ble/test 'ble/array#remove-at a 7; status' stdout="23:(${a3[*]})"
    479 )
    480 
    481 # ble/string#reserve-prototype
    482 (
    483   _ble_string_prototype='        '
    484   ble/test 'echo "${#_ble_string_prototype}"' stdout=8
    485   ble/string#reserve-prototype 10
    486   ble/test 'echo "${#_ble_string_prototype}"' stdout=16
    487   ble/test 'x=${_ble_string_prototype::10}; echo "${#x}"' stdout=10
    488   ble/string#reserve-prototype 3
    489   ble/test 'echo "${#_ble_string_prototype}"' stdout=16
    490   ble/test 'x=${_ble_string_prototype::3}; echo "${#x}"' stdout=3
    491   ble/string#reserve-prototype 77
    492   ble/test 'echo "${#_ble_string_prototype}"' stdout=128
    493   ble/test 'x=${_ble_string_prototype::77}; echo "${#x}"' stdout=77
    494 )
    495 
    496 # ble/string#repeat
    497 (
    498   ble/test 'ble/string#repeat' ret=
    499   ble/test 'ble/string#repeat ""' ret=
    500   ble/test 'ble/string#repeat a' ret=
    501   ble/test 'ble/string#repeat abc' ret=
    502   ble/test 'ble/string#repeat "" ""' ret=
    503   ble/test 'ble/string#repeat a ""' ret=
    504   ble/test 'ble/string#repeat abc ""' ret=
    505   ble/test 'ble/string#repeat "" 0' ret=
    506   ble/test 'ble/string#repeat a 0' ret=
    507   ble/test 'ble/string#repeat abc 0' ret=
    508   ble/test 'ble/string#repeat "" 1' ret=
    509   ble/test 'ble/string#repeat "" 10' ret=
    510 
    511   ble/test 'ble/string#repeat a 1' ret=a
    512   ble/test 'ble/string#repeat a 2' ret=aa
    513   ble/test 'ble/string#repeat a 5' ret=aaaaa
    514   ble/test 'ble/string#repeat abc 1' ret=abc
    515   ble/test 'ble/string#repeat abc 2' ret=abcabc
    516   ble/test 'ble/string#repeat abc 5' ret=abcabcabcabcabc
    517   ble/test 'ble/string#repeat ";&|<>" 5' ret=';&|<>;&|<>;&|<>;&|<>;&|<>'
    518 )
    519 
    520 # ToDo
    521 # ble/array#shift
    522 # ble/array#filter
    523 # ble/array#remove-if
    524 # ble/array#filter-by-regex
    525 # ble/array#remove-by-regex
    526 # ble/array#filter-by-glob
    527 # ble/array#remove-by-glob
    528 # ble/array#fill-range
    529 # ble/idict#replace
    530 # ble/idict#copy
    531 
    532 # ble/string#common-prefix
    533 (
    534   ble/test 'ble/string#common-prefix' ret=
    535   ble/test 'ble/string#common-prefix ""' ret=
    536   ble/test 'ble/string#common-prefix a' ret=
    537   ble/test 'ble/string#common-prefix "" ""' ret=
    538   ble/test 'ble/string#common-prefix a ""' ret=
    539   ble/test 'ble/string#common-prefix a b' ret=
    540   ble/test 'ble/string#common-prefix a a' ret=a
    541   ble/test 'ble/string#common-prefix abc abc' ret=abc
    542   ble/test 'ble/string#common-prefix abc aaa' ret=a
    543   ble/test 'ble/string#common-prefix abc ccc' ret=
    544   ble/test 'ble/string#common-prefix abc xyz' ret=
    545 )
    546 
    547 # ble/string#common-suffix
    548 (
    549   ble/test 'ble/string#common-suffix' ret=
    550   ble/test 'ble/string#common-suffix ""' ret=
    551   ble/test 'ble/string#common-suffix a' ret=
    552   ble/test 'ble/string#common-suffix "" ""' ret=
    553   ble/test 'ble/string#common-suffix a ""' ret=
    554   ble/test 'ble/string#common-suffix a b' ret=
    555   ble/test 'ble/string#common-suffix a a' ret=a
    556   ble/test 'ble/string#common-suffix abc abc' ret=abc
    557   ble/test 'ble/string#common-suffix abc aaa' ret=
    558   ble/test 'ble/string#common-suffix abc ccc' ret=c
    559   ble/test 'ble/string#common-suffix abc xyz' ret=
    560 )
    561 
    562 # ble/string#split
    563 (
    564   function status { ble/util/print "${#a[@]}:(""${a[*]}"")"; }
    565   nl=$'\n'
    566   ble/test 'ble/string#split a , ""  ; status' stdout='1:()'
    567   ble/test 'ble/string#split a , "1"  ; status' stdout='1:(1)'
    568   ble/test 'ble/string#split a , ","  ; status' stdout='2:( )'
    569   ble/test 'ble/string#split a , "1,"  ; status' stdout='2:(1 )'
    570   ble/test 'ble/string#split a , ",2"  ; status' stdout='2:( 2)'
    571   ble/test 'ble/string#split a , "1,,3"  ; status' stdout='3:(1  3)'
    572   ble/test 'ble/string#split a , "1,2,3"  ; status' stdout='3:(1 2 3)'
    573   ble/test 'ble/string#split a " " "1 2 3"; status' stdout='3:(1 2 3)'
    574   ble/test 'ble/string#split a " " "1	2	3"; status' stdout='1:(1	2	3)'
    575   ble/test 'ble/string#split a " " "1'"$nl"'2'"$nl"'3"; status' stdout="1:(1${nl}2${nl}3)"
    576 )
    577 
    578 # ble/string#split-words
    579 (
    580   function status { ble/util/print "${#a[@]}:(${a[*]})"; }
    581   nl=$'\n' ht=$'\t'
    582   ble/test 'ble/string#split-words a ""  ; status' stdout='0:()'
    583   ble/test 'ble/string#split-words a "1"  ; status' stdout='1:(1)'
    584   ble/test 'ble/string#split-words a " "  ; status' stdout='0:()'
    585   ble/test 'ble/string#split-words a "1 "  ; status' stdout='1:(1)'
    586   ble/test 'ble/string#split-words a " 2"  ; status' stdout='1:(2)'
    587   ble/test 'ble/string#split-words a "1  3"  ; status' stdout='2:(1 3)'
    588   ble/test 'ble/string#split-words a "1 2 3"; status' stdout='3:(1 2 3)'
    589   ble/test 'ble/string#split-words a "  1'"$ht"'2'"$ht"'3  "; status' stdout='3:(1 2 3)'
    590   ble/test 'ble/string#split-words a "  1'"$nl"'2'"$nl"'3  "; status' stdout='3:(1 2 3)'
    591 )
    592 
    593 # ble/string#split-lines
    594 (
    595   function status { ble/util/print "${#a[@]}:(""${a[*]}"")"; }
    596   nl=$'\n' ht=$'\t'
    597   ble/test 'ble/string#split-lines a ""  ; status' stdout='1:()'
    598   ble/test 'ble/string#split-lines a "1"  ; status' stdout='1:(1)'
    599   ble/test 'ble/string#split-lines a "'"$nl"'"  ; status' stdout='2:( )'
    600   ble/test 'ble/string#split-lines a "1'"$nl"'"  ; status' stdout='2:(1 )'
    601   ble/test 'ble/string#split-lines a "'"$nl"'2"  ; status' stdout='2:( 2)'
    602   ble/test 'ble/string#split-lines a "1'"$nl$nl"'3"  ; status' stdout='3:(1  3)'
    603   ble/test 'ble/string#split-lines a "1'"$nl"'2'"$nl"'3"; status' stdout='3:(1 2 3)'
    604   ble/test 'ble/string#split-lines a "1'"$ht"'2'"$ht"'3"; status' stdout="1:(1${ht}2${ht}3)"
    605   ble/test 'ble/string#split-lines a "1 2 3"; status' stdout="1:(1 2 3)"
    606 )
    607 
    608 # ble/string#count-char
    609 (
    610   #UB: ble/test 'ble/string#count-char hello' ret=5
    611   ble/test 'ble/string#count-char hello a' ret=0
    612   ble/test 'ble/string#count-char hello あ' ret=0
    613   ble/test 'ble/string#count-char hello e' ret=1
    614   ble/test 'ble/string#count-char hello l' ret=2
    615   ble/test 'ble/string#count-char hello olh' ret=4
    616   ble/test 'ble/string#count-char hello hello' ret=5
    617   ble/test 'ble/string#count-char "" a' ret=0
    618   ble/test 'ble/string#count-char "" ab' ret=0
    619 )
    620 
    621 # ble/string#count-string
    622 (
    623   ble/test 'ble/string#count-string hello a' ret=0
    624   ble/test 'ble/string#count-string hello あ' ret=0
    625   ble/test 'ble/string#count-string hello ee' ret=0
    626   ble/test 'ble/string#count-string hello e' ret=1
    627   ble/test 'ble/string#count-string hello l' ret=2
    628   ble/test 'ble/string#count-string hello ll' ret=1
    629   ble/test 'ble/string#count-string hello hello' ret=1
    630   ble/test 'ble/string#count-string "" a' ret=0
    631   ble/test 'ble/string#count-string "" ab' ret=0
    632   ble/test 'ble/string#count-string ababababa aba' ret=2
    633 )
    634 
    635 # ble/string#index-of
    636 (
    637   ble/test 'ble/string#index-of hello a' ret=-1
    638   ble/test 'ble/string#index-of hello あ' ret=-1
    639   ble/test 'ble/string#index-of hello ee' ret=-1
    640   ble/test 'ble/string#index-of hello e' ret=1
    641   ble/test 'ble/string#index-of hello l' ret=2
    642   ble/test 'ble/string#index-of hello ll' ret=2
    643   ble/test 'ble/string#index-of hello hello' ret=0
    644   ble/test 'ble/string#index-of "" a' ret=-1
    645   ble/test 'ble/string#index-of "" ab' ret=-1
    646   ble/test 'ble/string#index-of ababababa aba' ret=0
    647 )
    648 
    649 # ble/string#last-index-of
    650 (
    651   ble/test 'ble/string#last-index-of hello a' ret=-1
    652   ble/test 'ble/string#last-index-of hello あ' ret=-1
    653   ble/test 'ble/string#last-index-of hello ee' ret=-1
    654   ble/test 'ble/string#last-index-of hello e' ret=1
    655   ble/test 'ble/string#last-index-of hello l' ret=3
    656   ble/test 'ble/string#last-index-of hello ll' ret=2
    657   ble/test 'ble/string#last-index-of hello hello' ret=0
    658   ble/test 'ble/string#last-index-of "" a' ret=-1
    659   ble/test 'ble/string#last-index-of "" ab' ret=-1
    660   ble/test 'ble/string#last-index-of ababababa aba' ret=6
    661 )
    662 
    663 # ble/string#{toggle-case,tolower,toupper,capitalize}
    664 (
    665   ble/test 'ble/string#toggle-case' ret=
    666   ble/test 'ble/string#tolower    ' ret=
    667   ble/test 'ble/string#toupper    ' ret=
    668   ble/test 'ble/string#capitalize ' ret=
    669   ble/test 'ble/string#toggle-case ""' ret=
    670   ble/test 'ble/string#tolower     ""' ret=
    671   ble/test 'ble/string#toupper     ""' ret=
    672   ble/test 'ble/string#capitalize  ""' ret=
    673   ble/test 'ble/string#toggle-case a' ret=A
    674   ble/test 'ble/string#tolower     a' ret=a
    675   ble/test 'ble/string#toupper     a' ret=A
    676   ble/test 'ble/string#capitalize  a' ret=A
    677   ble/test 'ble/string#toggle-case あ' ret=あ
    678   ble/test 'ble/string#tolower     あ' ret=あ
    679   ble/test 'ble/string#toupper     あ' ret=あ
    680   ble/test 'ble/string#capitalize  あ' ret=あ
    681   ble/test 'ble/string#toggle-case +' ret=+
    682   ble/test 'ble/string#tolower     +' ret=+
    683   ble/test 'ble/string#toupper     +' ret=+
    684   ble/test 'ble/string#capitalize  +' ret=+
    685   ble/test 'ble/string#toggle-case abc' ret=ABC
    686   ble/test 'ble/string#tolower     abc' ret=abc
    687   ble/test 'ble/string#toupper     abc' ret=ABC
    688   ble/test 'ble/string#capitalize  abc' ret=Abc
    689   ble/test 'ble/string#toggle-case ABC' ret=abc
    690   ble/test 'ble/string#tolower     ABC' ret=abc
    691   ble/test 'ble/string#toupper     ABC' ret=ABC
    692   ble/test 'ble/string#capitalize  ABC' ret=Abc
    693   ble/test 'ble/string#toggle-case aBc' ret=AbC
    694   ble/test 'ble/string#tolower     aBc' ret=abc
    695   ble/test 'ble/string#toupper     aBc' ret=ABC
    696   ble/test 'ble/string#capitalize  aBc' ret=Abc
    697   ble/test 'ble/string#toggle-case +aBc' ret=+AbC
    698   ble/test 'ble/string#tolower     +aBc' ret=+abc
    699   ble/test 'ble/string#toupper     +aBc' ret=+ABC
    700   ble/test 'ble/string#capitalize  +aBc' ret=+Abc
    701   ble/test 'ble/string#capitalize  "hello world"' ret='Hello World'
    702 
    703   LC_ALL=en_US.utf8
    704   ble/test 'ble/string#toggle-case +aBc' ret=+AbC
    705   ble/test 'ble/string#tolower     +aBc' ret=+abc
    706   ble/test 'ble/string#toupper     +aBc' ret=+ABC
    707   ble/test 'ble/string#capitalize  +aBc' ret=+Abc
    708   ble/test 'ble/string#capitalize  "hello world"' ret='Hello World'
    709 )
    710 
    711 # ble/string#{trim,ltrim,rtrim}
    712 (
    713   ble/test 'ble/string#trim ' ret=
    714   ble/test 'ble/string#ltrim' ret=
    715   ble/test 'ble/string#rtrim' ret=
    716   ble/test 'ble/string#trim  ""' ret=
    717   ble/test 'ble/string#ltrim ""' ret=
    718   ble/test 'ble/string#rtrim ""' ret=
    719   ble/test 'ble/string#trim  "a"' ret=a
    720   ble/test 'ble/string#ltrim "a"' ret=a
    721   ble/test 'ble/string#rtrim "a"' ret=a
    722   ble/test 'ble/string#trim  " a "' ret=a
    723   ble/test 'ble/string#ltrim " a "' ret='a '
    724   ble/test 'ble/string#rtrim " a "' ret=' a'
    725   ble/test 'ble/string#trim  " a b "' ret='a b'
    726   ble/test 'ble/string#ltrim " a b "' ret='a b '
    727   ble/test 'ble/string#rtrim " a b "' ret=' a b'
    728   ble/test 'ble/string#trim  "abc"' ret='abc'
    729   ble/test 'ble/string#ltrim "abc"' ret='abc'
    730   ble/test 'ble/string#rtrim "abc"' ret='abc'
    731   ble/test 'ble/string#trim  "  abc  "' ret='abc'
    732   ble/test 'ble/string#ltrim "  abc  "' ret='abc  '
    733   ble/test 'ble/string#rtrim "  abc  "' ret='  abc'
    734   for pad in $' \t\n \t\n' $'\t\t\t' $'\n\n\n'; do
    735     ble/test 'ble/string#trim  "'"$pad"'abc'"$pad"'"' ret='abc'
    736     ble/test 'ble/string#ltrim "'"$pad"'abc'"$pad"'"' ret="abc${pad}"
    737     ble/test 'ble/string#rtrim "'"$pad"'abc'"$pad"'"' ret="${pad}abc"
    738   done
    739 )
    740 
    741 # ble/string#escape-characters
    742 (
    743   ble/test 'ble/string#escape-characters hello' ret=hello
    744   ble/test 'ble/string#escape-characters hello ""' ret=hello
    745   ble/test 'ble/string#escape-characters hello xyz' ret=hello
    746   ble/test 'ble/string#escape-characters hello el' ret='h\e\l\lo'
    747   ble/test 'ble/string#escape-characters hello hl XY' ret='\Xe\Y\Yo'
    748 
    749   # regex
    750   ble/test 'ble/string#escape-for-sed-regex      "A\.[*?+|^\$(){}/"' \
    751            ret='A\\\.\[\*?+|\^\$(){}\/'
    752   ble/test 'ble/string#escape-for-awk-regex      "A\.[*?+|^\$(){}/"' \
    753            ret='A\\\.\[\*\?\+\|\^\$\(\)\{\}\/'
    754   ble/test 'ble/string#escape-for-extended-regex "A\.[*?+|^\$(){}/"' \
    755            ret='A\\\.\[\*\?\+\|\^\$\(\)\{\}/'
    756 
    757   # bash
    758   ble/test 'ble/string#escape-for-bash-glob "A\*?[("' ret='A\\\*\?\[\('
    759   ble/test 'ble/string#escape-for-bash-single-quote "A'\''B"' ret="A'\''B"
    760   ble/test 'ble/string#escape-for-bash-double-quote "hello \$ \` \\ ! world"' ret='hello \$ \` \\ "\!" world'
    761   input=A$'\\\a\b\e\f\n\r\t\v'\'B output=A'\\\a\b\e\f\n\r\t\v\'\'B
    762   ble/test 'ble/string#escape-for-bash-escape-string "$input"' ret="$output"
    763   ble/test 'ble/string#escape-for-bash-specialchars "[hello] (world) {this,is} <test>"' \
    764            ret='\[hello\]\ \(world\)\ {this,is}\ \<test\>'
    765   ble/test 'ble/string#escape-for-bash-specialchars "[hello] (world) {this,is} <test>" b' \
    766            ret='\[hello\]\ \(world\)\ \{this\,is\}\ \<test\>'
    767   ble/test 'ble/string#escape-for-bash-specialchars "a=b:c:d" c' \
    768            ret='a\=b\:c\:d'
    769   ble/test $'ble/string#escape-for-bash-specialchars "a\tb\tc"' \
    770            ret=$'a\\\tb\\\tc'
    771 )
    772 
    773 # ToDo
    774 # ble/string#escape-for-display
    775 # ble/string#quote-words
    776 # ble/string#match
    777 
    778 # ble/string#quote-command, ble/util/print-quoted-command
    779 (
    780   ble/test 'ble/string#quote-command' ret=
    781   ble/test 'ble/string#quote-command echo' ret='echo'
    782   ble/test 'ble/string#quote-command echo hello world' ret="echo 'hello' 'world'"
    783   ble/test 'ble/string#quote-command echo "hello world"' ret="echo 'hello world'"
    784   ble/test 'ble/string#quote-command echo "'\''test'\''"' ret="echo ''\''test'\'''"
    785   ble/test 'ble/string#quote-command echo "" "" ""' ret="echo '' '' ''"
    786   ble/test 'ble/string#quote-command echo a{1..4}' ret="echo 'a1' 'a2' 'a3' 'a4'"
    787 
    788   ble/test 'ble/util/print-quoted-command' stdout=
    789   ble/test 'ble/util/print-quoted-command echo' stdout='echo'
    790   ble/test 'ble/util/print-quoted-command echo hello world' stdout="echo 'hello' 'world'"
    791   ble/test 'ble/util/print-quoted-command echo "hello world"' stdout="echo 'hello world'"
    792   ble/test 'ble/util/print-quoted-command echo "'\''test'\''"' stdout="echo ''\''test'\'''"
    793   ble/test 'ble/util/print-quoted-command echo "" "" ""' stdout="echo '' '' ''"
    794   ble/test 'ble/util/print-quoted-command echo a{1..4}' stdout="echo 'a1' 'a2' 'a3' 'a4'"
    795 )
    796 # ble/string#quote-word
    797 (
    798   ble/test 'ble/string#quote-word' ret=
    799   ble/test 'ble/string#quote-word echo' ret='echo'
    800   ble/test 'ble/string#quote-word "hello world"' ret="'hello world'"
    801   ble/test 'ble/string#quote-word "'\''test'\''"' ret="\'test\'"
    802   ble/test 'ble/string#quote-word "a'\''b'\''c"' ret="a\'b\'c"
    803 )
    804 
    805 # ble/string#create-unicode-progress-bar
    806 (
    807   ble/test 'ble/string#create-unicode-progress-bar  0 24 3' ret='   '
    808   ble/test 'ble/string#create-unicode-progress-bar  1 24 3' ret='▏  '
    809   ble/test 'ble/string#create-unicode-progress-bar  2 24 3' ret='▎  '
    810   ble/test 'ble/string#create-unicode-progress-bar  3 24 3' ret='▍  '
    811   ble/test 'ble/string#create-unicode-progress-bar  4 24 3' ret='▌  '
    812   ble/test 'ble/string#create-unicode-progress-bar  5 24 3' ret='▋  '
    813   ble/test 'ble/string#create-unicode-progress-bar  6 24 3' ret='▊  '
    814   ble/test 'ble/string#create-unicode-progress-bar  7 24 3' ret='▉  '
    815   ble/test 'ble/string#create-unicode-progress-bar  8 24 3' ret='█  '
    816   ble/test 'ble/string#create-unicode-progress-bar  9 24 3' ret='█▏ '
    817   ble/test 'ble/string#create-unicode-progress-bar 15 24 3' ret='█▉ '
    818   ble/test 'ble/string#create-unicode-progress-bar 16 24 3' ret='██ '
    819   ble/test 'ble/string#create-unicode-progress-bar 17 24 3' ret='██▏'
    820   ble/test 'ble/string#create-unicode-progress-bar 24 24 3' ret='███'
    821   ble/test 'ble/string#create-unicode-progress-bar  0 24 4 unlimited' ret=$'█   '
    822   ble/test 'ble/string#create-unicode-progress-bar  1 24 4 unlimited' ret=$'\e[7m▏\e[27m▏  '
    823   ble/test 'ble/string#create-unicode-progress-bar  2 24 4 unlimited' ret=$'\e[7m▎\e[27m▎  '
    824   ble/test 'ble/string#create-unicode-progress-bar  3 24 4 unlimited' ret=$'\e[7m▍\e[27m▍  '
    825   ble/test 'ble/string#create-unicode-progress-bar  4 24 4 unlimited' ret=$'\e[7m▌\e[27m▌  '
    826   ble/test 'ble/string#create-unicode-progress-bar  5 24 4 unlimited' ret=$'\e[7m▋\e[27m▋  '
    827   ble/test 'ble/string#create-unicode-progress-bar  6 24 4 unlimited' ret=$'\e[7m▊\e[27m▊  '
    828   ble/test 'ble/string#create-unicode-progress-bar  7 24 4 unlimited' ret=$'\e[7m▉\e[27m▉  '
    829   ble/test 'ble/string#create-unicode-progress-bar  8 24 4 unlimited' ret=$' █  '
    830   ble/test 'ble/string#create-unicode-progress-bar  9 24 4 unlimited' ret=$' \e[7m▏\e[27m▏ '
    831   ble/test 'ble/string#create-unicode-progress-bar 15 24 4 unlimited' ret=$' \e[7m▉\e[27m▉ '
    832   ble/test 'ble/string#create-unicode-progress-bar 16 24 4 unlimited' ret=$'  █ '
    833   ble/test 'ble/string#create-unicode-progress-bar 17 24 4 unlimited' ret=$'  \e[7m▏\e[27m▏'
    834   ble/test 'ble/string#create-unicode-progress-bar 24 24 4 unlimited' ret=$'█   '
    835 )
    836 
    837 # ble/util/strlen
    838 (
    839   ble/test 'ble/util/strlen' ret=0
    840   ble/test 'ble/util/strlen ""' ret=0
    841   ble/test 'ble/util/strlen a' ret=1
    842   ble/test 'ble/util/strlen abc' ret=3
    843   ble/test 'ble/util/strlen α' ret=2
    844   ble/test 'ble/util/strlen αβγ' ret=6
    845   ble/test 'ble/util/strlen あ' ret=3
    846   ble/test 'ble/util/strlen あいう' ret=9
    847   ble/test 'ble/util/strlen aα' ret=3
    848   ble/test 'ble/util/strlen aαあ' ret=6
    849 
    850   LC_ALL=en_US.utf8
    851   ble/test 'ble/util/strlen a' ret=1
    852   ble/test 'ble/util/strlen α' ret=2
    853   ble/test 'ble/util/strlen あ' ret=3
    854 )
    855 
    856 # ble/util/substr
    857 (
    858   ble/test 'ble/util/substr' ret=
    859   ble/test 'ble/util/substr ""' ret=
    860   ble/test 'ble/util/substr a' ret=
    861   ble/test 'ble/util/substr "" 0' ret=
    862   ble/test 'ble/util/substr "" 1' ret=
    863   ble/test 'ble/util/substr a 0' ret=
    864   ble/test 'ble/util/substr a 1' ret=
    865   ble/test 'ble/util/substr a 2' ret=
    866   ble/test 'ble/util/substr "" 0 0' ret=
    867   ble/test 'ble/util/substr "" 0 1' ret=
    868   ble/test 'ble/util/substr "" 1 1' ret=
    869   ble/test 'ble/util/substr a 0 0' ret=
    870   ble/test 'ble/util/substr a 1 0' ret=
    871   ble/test 'ble/util/substr a 0 1' ret=a
    872   ble/test 'ble/util/substr a 1 1' ret=
    873   ble/test 'ble/util/substr abc 1 0' ret=
    874   ble/test 'ble/util/substr abc 1 1' ret=b
    875   ble/test 'ble/util/substr abc 1 2' ret=bc
    876   ble/test 'ble/util/substr abc 0 0' ret=
    877   ble/test 'ble/util/substr abc 0 1' ret=a
    878   ble/test 'ble/util/substr abc 0 3' ret=abc
    879   ble/test 'ble/util/substr abc 0 4' ret=abc
    880   ble/test 'ble/util/substr abc 3 0' ret=
    881   ble/test 'ble/util/substr abc 3 1' ret=
    882   ble/test 'ble/util/substr abc 4 0' ret=
    883   ble/test 'ble/util/substr abc 4 1' ret=
    884 
    885   ble/test 'ble/util/substr あいう 0 3' ret=あ
    886   ble/test 'ble/util/substr あいう 3 6' ret=いう
    887   ble/test 'ble/util/substr あいう 0 1' ret=$'\xe3'
    888   ble/test 'ble/util/substr あいう 1 2' ret=$'\x81\x82'
    889   ble/test 'ble/util/substr あいう 1 4' ret=$'\x81\x82\xe3\x81'
    890   ble/test 'ble/util/substr あいう 7 5' ret=$'\x81\x86'
    891 )
    892 
    893 # ble/path#remove{,-glob}
    894 (
    895   for cmd in ble/path#{remove,remove-glob}; do
    896     ble/test code:'ret=; '$cmd' ret' ret=
    897     ble/test code:'ret=; '$cmd' ret ""' ret=
    898     ble/test code:'ret=a; '$cmd' ret ""' ret=a
    899     ble/test code:'ret=a; '$cmd' ret a' ret=
    900     ble/test code:'ret=a; '$cmd' ret b' ret=a
    901     ble/test code:'ret=a:a:a; '$cmd' ret a' ret=
    902     ble/test code:'ret=aa; '$cmd' ret a' ret=aa
    903     ble/test code:'ret=xyz:abc; '$cmd' ret ""' ret=xyz:abc
    904     ble/test code:'ret=xyz:abc; '$cmd' ret xyz' ret=abc
    905     ble/test code:'ret=xyz:abc; '$cmd' ret abc' ret=xyz
    906     ble/test code:'ret=xyz:abc:tuv; '$cmd' ret xyz' ret=abc:tuv
    907     ble/test code:'ret=xyz:abc:tuv; '$cmd' ret abc' ret=xyz:tuv
    908     ble/test code:'ret=xyz:abc:tuv; '$cmd' ret tuv' ret=xyz:abc
    909     ble/test code:'ret=xyz:xyz; '$cmd' ret xyz' ret=
    910     ble/test code:'ret=xyz:abc:xyz; '$cmd' ret xyz' ret=abc
    911     ble/test code:'ret=xyz:abc:xyz; '$cmd' ret abc' ret=xyz:xyz
    912     ble/test code:'ret=xyz:xyz:xyz; '$cmd' ret xyz' ret=
    913   done
    914 
    915   ble/test code:'ret=a; ble/path#remove ret \?' ret=a
    916   ble/test code:'ret=aa; ble/path#remove ret \?' ret=aa
    917   ble/test code:'ret=a:b; ble/path#remove ret \?' ret=a:b
    918   ble/test code:'ret=a:b:c; ble/path#remove ret \?' ret=a:b:c
    919   ble/test code:'ret=aa:b:cc; ble/path#remove ret \?' ret=aa:b:cc
    920   ble/test code:'ret=stdX:stdY:usrZ; ble/path#remove ret "std[a-zX-Z]"' ret=stdX:stdY:usrZ
    921   ble/test code:'ret=stdX:usrZ:stdY; ble/path#remove ret "std[a-zX-Z]"' ret=stdX:usrZ:stdY
    922   ble/test code:'ret=usrZ:stdX:stdY; ble/path#remove ret "std[a-zX-Z]"' ret=usrZ:stdX:stdY
    923 
    924   ble/test code:'ret=a; ble/path#remove-glob ret \?' ret=
    925   ble/test code:'ret=aa; ble/path#remove-glob ret \?' ret=aa
    926   ble/test code:'ret=a:b; ble/path#remove-glob ret \?' ret=
    927   ble/test code:'ret=a:b:c; ble/path#remove-glob ret \?' ret=
    928   ble/test code:'ret=aa:b:cc; ble/path#remove-glob ret \?' ret=aa:cc
    929   ble/test code:'ret=stdX:stdY:usrZ; ble/path#remove-glob ret "std[a-zX-Z]"' ret=usrZ
    930   ble/test code:'ret=stdX:usrZ:stdY; ble/path#remove-glob ret "std[a-zX-Z]"' ret=usrZ
    931   ble/test code:'ret=usrZ:stdX:stdY; ble/path#remove-glob ret "std[a-zX-Z]"' ret=usrZ
    932 )
    933 
    934 # ble/path#{append,prepend,contains}
    935 (
    936   ble/test code:'ret=; ble/path#append ret a' ret=a
    937   ble/test code:'ret=a; ble/path#append ret a' ret=a:a
    938   ble/test code:'ret=a; ble/path#append ret b' ret=a:b
    939   ble/test code:'ret=a:b; ble/path#append ret cd' ret=a:b:cd
    940   ble/test code:'ret=; ble/path#prepend ret a' ret=a
    941   ble/test code:'ret=a; ble/path#prepend ret a' ret=a:a
    942   ble/test code:'ret=a; ble/path#prepend ret b' ret=b:a
    943   ble/test code:'ret=a:b; ble/path#prepend ret cd' ret=cd:a:b
    944 
    945   ble/test code:'ret=a:b:c; ble/path#contains ret a'
    946   ble/test code:'ret=a:b:c; ble/path#contains ret b'
    947   ble/test code:'ret=a:b:c; ble/path#contains ret c'
    948   ble/test code:'ret=a:b:c; ! ble/path#contains ret x'
    949   ble/test code:'ret=a:b:c; ! ble/path#contains ret aa'
    950   ble/test code:'ret=a:b:c; ! ble/path#contains ret bb'
    951   ble/test code:'ret=a:b:c; ! ble/path#contains ret cc'
    952   ble/test code:'ret=a:b:c; ! ble/path#contains ret "?"'
    953   ble/test code:'ret=a:b:c; ! ble/path#contains ret "*"'
    954 
    955   ble/test code:'ret=abc:def; ble/path#contains ret abc'
    956   ble/test code:'ret=abc:def; ble/path#contains ret def'
    957   ble/test code:'ret=abc:def; ! ble/path#contains ret a'
    958   ble/test code:'ret=abc:def; ! ble/path#contains ret ab'
    959   ble/test code:'ret=abc:def; ! ble/path#contains ret abcdef'
    960   ble/test code:'ret=abc:def; ! ble/path#contains ret "???"'
    961   ble/test code:'ret=xyz; ble/path#contains ret xyz'
    962   ble/test code:'ret=xyz; ! ble/path#contains ret xyz:xyz'
    963   ble/test code:'ret=xyz; ! ble/path#contains ret "???"'
    964 )
    965 
    966 # ToDo
    967 # ble/path#contains
    968 # ble/opts#has
    969 # ble/opts#extract-first-optarg
    970 # ble/opts#extract-last-optarg
    971 # ble/opts#extract-all-optargs
    972 # ble/set#add
    973 # ble/set#remove
    974 # ble/set#contains
    975 # ble/set#add
    976 # ble/set#remove
    977 # ble/set#contains
    978 
    979 # ToDo
    980 # ble/dict#clear
    981 # ble/dict#cp
    982 # ble/dict#keys
    983 # ble/dict#print
    984 # ble/gdict#clear
    985 # ble/gdict#cp
    986 # ble/gdict#keys
    987 # ble/gdict#print
    988 # ble/adict#clear
    989 # ble/adict#cp
    990 # ble/adict#keys
    991 # ble/adict#print
    992 
    993 # ble/dict#{set,get,has,unset}
    994 (
    995   builtin eval -- "${_ble_util_dict_declare//NAME/dict1}"
    996   builtin eval -- "${_ble_util_gdict_declare//NAME/dict2}"
    997   builtin eval -- "${_ble_util_adict_declare//NAME/dict3}"
    998   index=1
    999   for Dict in ble/{,g,a}dict; do
   1000     dict=dict$((index++))
   1001 
   1002     ret=unchanged
   1003     ble/test '! '$Dict'#has '$dict' banana' ret=unchanged
   1004     ble/test '! '$Dict'#has '$dict' ""' ret=unchanged
   1005 
   1006     $Dict#set $dict apple red
   1007     $Dict#set $dict banana yellow
   1008     $Dict#set $dict orange orange
   1009     $Dict#set $dict melon green
   1010   
   1011     ret=unchanged
   1012     ble/test $Dict'#has '$dict' banana' ret=unchanged # 先頭
   1013     ble/test $Dict'#has '$dict' apple'  ret=unchanged # 中
   1014     ble/test $Dict'#has '$dict' melon'  ret=unchanged # 末尾
   1015     ble/test '! '$Dict'#has '$dict' pear' ret=unchanged # 存在しない項目
   1016     ble/test $Dict'#get '$dict' banana' ret=yellow   # 先頭
   1017     ble/test $Dict'#get '$dict' apple'  ret=red      # 中
   1018     ble/test $Dict'#get '$dict' melon'  ret=green    # 末尾
   1019     ble/test '! '$Dict'#get '$dict' pear' ret=         # 存在しない項目
   1020   
   1021     # 空白類
   1022     ble/test '! '$Dict'#has '$dict' ""' # 末尾空要素で引けるか
   1023     ble/test '! '$Dict'#get '$dict' ""' # 末尾空要素で引けるか
   1024     $Dict#set $dict '' transparent
   1025     ble/test $Dict'#has '$dict' ""' # 末尾空要素で引けるか
   1026     ble/test $Dict'#get '$dict' ""' ret=transparent # 末尾空要素で引けるか
   1027     $Dict#set $dict 'alpha beta' pink
   1028     ble/test $Dict'#has '$dict' ""' # 中央空要素で引けるか
   1029     ble/test $Dict'#has '$dict' "alpha beta"' # 空白を含む見出し
   1030     ble/test $Dict'#get '$dict' ""' ret=transparent # 中央空要素で引けるか
   1031     ble/test $Dict'#get '$dict' "alpha beta"' ret=pink # 空白を含む見出し
   1032     $Dict#set $dict ' apple ' ' red '
   1033     ble/test $Dict'#has '$dict' " apple "' # 空白で trim されないか
   1034     ble/test $Dict'#has '$dict' apple' # 既存項目を破壊していないか
   1035     ble/test $Dict'#get '$dict' " apple "' ret=' red ' # 空白で trim されないか
   1036     ble/test $Dict'#get '$dict' apple' ret=red # 既存項目を破壊していないか
   1037   
   1038     # FS, colon
   1039     ble/test '! '$Dict'#has '$dict' "${_ble_term_FS}"' # 単一FS
   1040     ble/test '! '$Dict'#has '$dict' ":"' # 単一コロン
   1041     ble/test '! '$Dict'#has '$dict' "apple${_ble_term_FS}banana"' # FSを含む見出し
   1042     ble/test '! '$Dict'#has '$dict' apple:banana' # コロンを含む見出し
   1043     ble/test '! '$Dict'#get '$dict' "${_ble_term_FS}"' ret= # 単一FS
   1044     ble/test '! '$Dict'#get '$dict' ":"' ret= # 単一コロン
   1045     ble/test '! '$Dict'#get '$dict' "apple${_ble_term_FS}banana"' ret= # FSを含む見出し
   1046     ble/test '! '$Dict'#get '$dict' apple:banana' ret= # コロンを含む見出し
   1047     $Dict#set $dict "${_ble_term_FS}" Empty
   1048     $Dict#set $dict ":" Colon
   1049     $Dict#set $dict "apple${_ble_term_FS}banana" RedYellow
   1050     $Dict#set $dict "apple:banana" __red_yellow__
   1051     ble/test $Dict'#has '$dict' "${_ble_term_FS}"' # 単一FS
   1052     ble/test $Dict'#has '$dict' ":"' # 単一コロン
   1053     ble/test $Dict'#has '$dict' "apple${_ble_term_FS}banana"' # FSを含む見出し
   1054     ble/test $Dict'#has '$dict' apple:banana' # コロンを含む見出し
   1055     ble/test $Dict'#get '$dict' "${_ble_term_FS}"' ret=Empty # 単一FS
   1056     ble/test $Dict'#get '$dict' ":"' ret=Colon # 単一コロン
   1057     ble/test $Dict'#get '$dict' "apple${_ble_term_FS}banana"' ret=RedYellow # FSを含む見出し
   1058     ble/test $Dict'#get '$dict' apple:banana' ret=__red_yellow__ # コロンを含む見出し
   1059   
   1060     # unset
   1061     $Dict#unset $dict banana
   1062     $Dict#unset $dict apple
   1063     $Dict#unset $dict melon
   1064     ble/test '! '$Dict'#has '$dict' banana'
   1065     ble/test '! '$Dict'#has '$dict' apple'
   1066     ble/test '! '$Dict'#has '$dict' melon'
   1067     $Dict#unset $dict ""
   1068     $Dict#unset $dict "alpha beta"
   1069     $Dict#unset $dict " apple "
   1070     ble/test '! '$Dict'#has '$dict' ""' # 中央空要素で引けるか
   1071     ble/test '! '$Dict'#has '$dict' "alpha beta"' # 空白を含む見出し
   1072     ble/test '! '$Dict'#has '$dict' " apple "' # 空白で trim されないか
   1073     $Dict#unset $dict "${_ble_term_FS}"
   1074     $Dict#unset $dict ":"
   1075     $Dict#unset $dict "apple${_ble_term_FS}banana"
   1076     $Dict#unset $dict apple:banana
   1077     ble/test '! '$Dict'#has '$dict' "${_ble_term_FS}"' # 単一FS
   1078     ble/test '! '$Dict'#has '$dict' ":"' # 単一コロン
   1079     ble/test '! '$Dict'#has '$dict' "apple${_ble_term_FS}banana"' # FSを含む見出し
   1080     ble/test '! '$Dict'#has '$dict' apple:banana' # コロンを含む見出し
   1081   done
   1082 )
   1083 
   1084 # blehook
   1085 (
   1086   # declare hook
   1087   blehook/declare FOO
   1088   ble/test 'blehook --color=never FOO' stdout='blehook FOO='
   1089   ble/test 'blehook/has-hook FOO' exit=1
   1090 
   1091   # add/remove hook
   1092   blehook FOO+='ble/util/print hello'
   1093   ble/test 'blehook --color=never FOO' \
   1094            stdout="blehook FOO='ble/util/print hello'"
   1095   ble/test 'blehook/has-hook FOO'
   1096   blehook FOO+='ble/util/print world'
   1097   ble/test 'blehook --color=never FOO' \
   1098            stdout="blehook FOO='ble/util/print hello'" \
   1099            stdout="blehook FOO+='ble/util/print world'"
   1100   ble/test 'blehook/has-hook FOO'
   1101   blehook FOO-='ble/util/print hello'
   1102   ble/test 'blehook --color=never FOO' \
   1103            stdout="blehook FOO='ble/util/print world'"
   1104   ble/test 'blehook/has-hook FOO'
   1105   blehook FOO-='ble/util/print world'
   1106   ble/test 'blehook --color=never FOO' \
   1107            stdout='blehook FOO='
   1108   ble/test 'blehook/has-hook FOO' exit=1
   1109 
   1110   # reset hook
   1111   blehook FOO+='ble/util/print hello'
   1112   blehook FOO+='ble/util/print world'
   1113   blehook FOO='ble/util/print empty'
   1114   ble/test 'blehook --color=never FOO' \
   1115            stdout="blehook FOO='ble/util/print empty'"
   1116   ble/test 'blehook/has-hook FOO'
   1117 
   1118   # clear hook
   1119   blehook FOO+='ble/util/print hello'
   1120   blehook FOO+='ble/util/print world'
   1121   blehook FOO=
   1122   ble/test 'blehook --color=never FOO' \
   1123            stdout='blehook FOO='
   1124   ble/test 'blehook/has-hook FOO' exit=1
   1125 
   1126   # uniq hook
   1127   blehook FOO+='ble/util/print hello'
   1128   blehook FOO+='ble/util/print world'
   1129   blehook FOO!='ble/util/print hello'
   1130   ble/test 'blehook --color=never FOO' \
   1131            stdout="blehook FOO='ble/util/print hello'${_ble_term_nl}blehook FOO+='ble/util/print world'"
   1132   # uniq append
   1133   blehook FOO-+='ble/util/print hello'
   1134   ble/test 'blehook --color=never FOO' \
   1135            stdout="blehook FOO='ble/util/print world'${_ble_term_nl}blehook FOO+='ble/util/print hello'"
   1136   # uniq prepend
   1137   blehook FOO+-='ble/util/print hello'
   1138   ble/test 'blehook --color=never FOO' \
   1139            stdout="blehook FOO='ble/util/print hello'${_ble_term_nl}blehook FOO+='ble/util/print world'"
   1140 
   1141   # invoke hook
   1142   blehook FOO=
   1143   blehook FOO+='ble/util/print hello'
   1144   blehook FOO+='ble/util/print empty'
   1145   blehook FOO+='ble/util/print world'
   1146   ble/test 'blehook/invoke FOO' \
   1147            stdout=hello \
   1148            stdout=empty \
   1149            stdout=world
   1150   blehook FOO='ble/util/print "A$?"'
   1151   blehook FOO+='ble/util/print "B$?"'
   1152   blehook FOO+='ble/util/print "C$?"'
   1153   ble/test 'ble/util/setexit 123; blehook/invoke FOO' \
   1154            stdout=A123 \
   1155            stdout=B123 \
   1156            stdout=C123
   1157 
   1158   # eval-after-load
   1159   blehook/declare bar_load
   1160   blehook bar_load='ble/util/print bar_load'
   1161   ble/test 'blehook/eval-after-load bar "ble/util/print yes"' stdout=
   1162   ble/test 'blehook/invoke bar_load' \
   1163            stdout=bar_load \
   1164            stdout=yes
   1165   ble/test 'blehook/eval-after-load bar "ble/util/print next"' stdout=next
   1166 
   1167   # arguments
   1168   function func { ret="[$1]"; }
   1169   blehook FOO=func
   1170   ble/test 'blehook/invoke FOO xQAHbcpMFyFyQ' ret='[xQAHbcpMFyFyQ]'
   1171 )
   1172 
   1173 # ble/builtin/trap
   1174 (
   1175   # 0 / EXIT (special trap)
   1176   ble/builtin/trap 'ble/util/print TRAPEXIT1' 0
   1177   ble/test 'ble/builtin/trap/invoke 0' stdout=TRAPEXIT1
   1178   ble/test 'ble/builtin/trap/invoke EXIT' stdout=TRAPEXIT1
   1179   ble/builtin/trap 0
   1180   ble/test 'ble/builtin/trap/invoke 0' stdout=
   1181 
   1182   ble/builtin/trap 'ble/util/print TRAPEXIT2' EXIT
   1183   ble/test 'ble/builtin/trap/invoke 0' stdout=TRAPEXIT2
   1184   ble/test 'ble/builtin/trap/invoke EXIT' stdout=TRAPEXIT2
   1185   ble/builtin/trap EXIT
   1186   ble/test 'ble/builtin/trap/invoke 0' stdout=
   1187 
   1188   # 1 / HUP / SIGHUP (signal trap)
   1189   ble/builtin/trap 'ble/util/print TRAPHUP1' 1
   1190   ble/test 'ble/builtin/trap/invoke 1' stdout=TRAPHUP1
   1191   ble/test 'ble/builtin/trap/invoke HUP' stdout=TRAPHUP1
   1192   ble/test 'ble/builtin/trap/invoke SIGHUP' stdout=TRAPHUP1
   1193   ble/builtin/trap 1
   1194   ble/test 'ble/builtin/trap/invoke 1' stdout=
   1195 
   1196   ble/builtin/trap 'ble/util/print TRAPHUP2' HUP
   1197   ble/test 'ble/builtin/trap/invoke 1' stdout=TRAPHUP2
   1198   ble/test 'ble/builtin/trap/invoke HUP' stdout=TRAPHUP2
   1199   ble/test 'ble/builtin/trap/invoke SIGHUP' stdout=TRAPHUP2
   1200   ble/builtin/trap HUP
   1201   ble/test 'ble/builtin/trap/invoke HUP' stdout=
   1202 
   1203   ble/builtin/trap 'ble/util/print TRAPHUP3' SIGHUP
   1204   ble/test 'ble/builtin/trap/invoke 1' stdout=TRAPHUP3
   1205   ble/test 'ble/builtin/trap/invoke HUP' stdout=TRAPHUP3
   1206   ble/test 'ble/builtin/trap/invoke SIGHUP' stdout=TRAPHUP3
   1207   ble/builtin/trap SIGHUP
   1208   ble/test 'ble/builtin/trap/invoke HUP' stdout=
   1209 
   1210   # 9999 / CUSTOM (custom trap)
   1211   ble/builtin/trap/sig#new CUSTOM
   1212   ble/builtin/trap 'ble/util/print "custom trap"' CUSTOM
   1213   ble/test 'ble/builtin/trap/invoke CUSTOM' stdout='custom trap'
   1214   function ble/builtin/trap:CUSTOM { ble/util/print "__set_handler__ ($2) $1"; }
   1215   ble/test 'ble/builtin/trap "ble/util/print \"hello world\"" CUSTOM' \
   1216            stdout='__set_handler__ (CUSTOM) ble/util/print "hello world"'
   1217   ble/test 'ble/builtin/trap/invoke CUSTOM' stdout='hello world'
   1218 )
   1219 
   1220 # ble/util/{readfile,mapfile,assign,assign-array}
   1221 (
   1222   # readfile
   1223   ble/test 'ble/util/readfile ret <(echo hello)' \
   1224            ret=hello$'\n'
   1225   ble/test 'ble/util/readfile ret <(echo hello; echo world)' \
   1226            ret=hello$'\n'world$'\n'
   1227   ble/test 'ble/util/readfile ret <(echo hello; echo -n world)' \
   1228            ret=hello$'\n'world
   1229   ble/test 'ble/util/readfile ret <(:)' ret=
   1230 
   1231   # mapfile
   1232   function status { ble/util/print "${#a[*]}:(""${a[*]}"")"; }
   1233   ble/test "ble/util/mapfile a < <(echo hello); status" stdout='1:(hello)'
   1234   ble/test "ble/util/mapfile a < <(echo -n hello); status" stdout='1:(hello)'
   1235   ble/test "ble/util/mapfile a < <(echo hello; echo world); status" stdout='2:(hello world)'
   1236   ble/test "ble/util/mapfile a < <(echo hello; echo -n world); status" stdout='2:(hello world)'
   1237   ble/test "ble/util/mapfile a < <(printf '%s\n' h1 h2 h3 h4); status" stdout='4:(h1 h2 h3 h4)'
   1238   ble/test "ble/util/mapfile a < <(:); status" stdout='0:()'
   1239   ble/test "ble/util/mapfile a < <(echo); status" stdout='1:()'
   1240   ble/test "ble/util/mapfile a < <(echo;echo); status" stdout='2:( )'
   1241   ble/test "ble/util/mapfile a < <(echo a;echo;echo b); status" stdout='3:(a  b)'
   1242 
   1243   # assign
   1244   nl=$'\n'
   1245   ble/test 'ble/util/assign ret ""' ret=
   1246   ble/test 'ble/util/assign ret ":"' ret=
   1247   ble/test 'ble/util/assign ret "echo"' ret=
   1248   ble/test 'ble/util/assign ret "echo hello"' ret=hello
   1249   ble/test 'ble/util/assign ret "seq 5"' ret="1${nl}2${nl}3${nl}4${nl}5"
   1250   function f1 { ble/util/print stdout; ble/util/print stderr >&2; }
   1251   function nested-assign {
   1252     ble/util/assign err 'ble/util/assign out f1 2>&1'
   1253     ble/util/print "out=$out err=$err"
   1254   }
   1255   ble/test nested-assign stdout='out=stdout err=stderr'
   1256 
   1257   # assign-array
   1258   ble/test 'ble/util/assign-array a :; status' stdout='0:()'
   1259   ble/test 'ble/util/assign-array a echo; status' stdout='1:()'
   1260   ble/test 'ble/util/assign-array a "echo hello"; status' stdout='1:(hello)'
   1261   ble/test 'ble/util/assign-array a "seq 5"; status' stdout='5:(1 2 3 4 5)'
   1262   ble/test 'ble/util/assign-array a "echo; echo; echo"; status' stdout='3:(  )'
   1263   ble/test 'ble/util/assign-array a "echo 1; echo; echo 2"; status' stdout='3:(1  2)'
   1264 )
   1265 
   1266 # ToDo
   1267 # ble/util/copyfile
   1268 # ble/util/readarray
   1269 # ble/util/assign-array0
   1270 # ble/util/assign.has-output
   1271 # ble/util/assign-words
   1272 
   1273 # ble/util/writearray
   1274 (
   1275   # Note: Bash-3.x で arr=() の形式には ^A 及び ^? を変化させるバグが
   1276   # あるので、 改めて正しい値を代入する。
   1277   x=($'\177' $'\1' $'\2' $'\32' ' ' $'\a' $'\b' $'\t' $'\n' $'\v' $'\f' $'\r' a \" \' \$ \! \` \~)
   1278   x[0]=$'\177'
   1279   x[1]=$'\1'
   1280 
   1281   function ble/test/hash {
   1282     local tmpfile=$_ble_base_run/$$.test.$RANDOM ret
   1283     ble/bin/cat >| "$tmpfile"
   1284     ble/file#hash "$tmpfile"
   1285     >| "$tmpfile"
   1286     ble/util/print "$ret"
   1287   }
   1288 
   1289   ble/test "ble/util/writearray -d '' x | ble/test/hash" stdout=$(printf '%s\0' "${x[@]}" | ble/test/hash)
   1290 
   1291   # gawk では $'\302\203' という文字列を unescape する上で注意が必要
   1292   x=($'\302\203' alpha)
   1293   ble/test "ble/util/writearray -d '' x | ble/test/hash" stdout=$(printf '%s\0' "${x[@]}" | ble/test/hash)
   1294 
   1295   for pair in $'\a:007' $'\b:010' $'\t:011' $'\v:013' $'\f:014' $'\r:015'; do
   1296     for awk in awk nawk mawk gawk; do
   1297       if ble/is-function ble/bin/"$awk"; then
   1298         ctrl=${pair%:*}
   1299         seq=${pair#*:}
   1300         value=$(ble/bin/"$awk" '{gsub(/\'"$seq"'/, "<DEL>");print $0 "x";}' <<< "x${ctrl}y")
   1301         value=${value%x}
   1302         ble/test code:"ret=\$value # \"$awk gsub(/\\$seq/)\"" ret="x<DEL>y"
   1303       fi
   1304     done
   1305   done
   1306 )
   1307 
   1308 # ble/is-function
   1309 (
   1310   var=variable
   1311   alias ali=fun
   1312   function fun { ble/util/print "yes $*"; }
   1313   function ble/fun { ble/util/print "yes $*"; return 99; }
   1314   function ble/fun:type { ble/util/print "yes $*"; return 100; }
   1315   function ble/fun#meth { ble/util/print "yes $*"; return 101; }
   1316 
   1317   ble/test 'ble/is-function' exit=1
   1318   ble/test 'ble/is-function ""' exit=1
   1319 
   1320   ble/test 'ble/is-function fun'
   1321   ble/test 'ble/is-function ble/fun'
   1322   ble/test 'ble/is-function ble/fun:type'
   1323   ble/test 'ble/is-function ble/fun#meth'
   1324 
   1325   ble/test 'ble/is-function fun1' exit=1
   1326   ble/test 'ble/is-function ble/fun1' exit=1
   1327   ble/test 'ble/is-function ble/fun1:type' exit=1
   1328   ble/test 'ble/is-function ble/fun1#meth' exit=1
   1329 
   1330   ble/test 'ble/is-function ali' exit=1
   1331   ble/test 'ble/is-function var' exit=1
   1332   ble/test 'ble/is-function compgen' exit=1
   1333   ble/test 'ble/is-function declare' exit=1
   1334   ble/test 'ble/is-function mkfifo' exit=1
   1335 
   1336   function compgen { :; }
   1337   function declare { :; }
   1338   function mkfifo { :; }
   1339   ble/test 'ble/is-function compgen'
   1340   ble/test 'ble/is-function declare'
   1341   ble/test 'ble/is-function mkfifo'
   1342 
   1343   # ble/function#try
   1344   ble/test 'ble/function#try fun 1 2 3' stdout='yes 1 2 3'
   1345   ble/test 'ble/function#try ble/fun 1 2 3' stdout='yes 1 2 3' exit=99
   1346   ble/test 'ble/function#try ble/fun:type 1 2 3' stdout='yes 1 2 3' exit=100
   1347   ble/test 'ble/function#try ble/fun#meth 1 2 3' stdout='yes 1 2 3' exit=101
   1348   ble/test 'ble/function#try fun1 1 2 3' stdout= exit=127
   1349   ble/test 'ble/function#try ble/fun1 1 2 3' stdout= exit=127
   1350   ble/test 'ble/function#try ble/fun1:type 1 2 3' stdout= exit=127
   1351   ble/test 'ble/function#try ble/fun1#meth 1 2 3' stdout= exit=127
   1352 )
   1353 
   1354 # ble/function#advice
   1355 (
   1356   function f1 { ble/util/print "original${*:+ $*}"; }
   1357 
   1358   ble/test f1 stdout='original'
   1359   ble/function#advice before f1 'ble/util/print pre'
   1360   ble/test f1 stdout={pre,original}
   1361   ble/function#advice after f1 'ble/util/print post'
   1362   ble/test f1 stdout={pre,original,post}
   1363   ble/function#advice before f1 'ble/util/print A'
   1364   ble/test f1 stdout={A,original,post}
   1365   ble/function#advice after f1 'ble/util/print B'
   1366   ble/test f1 stdout={A,original,B}
   1367   ble/function#advice around f1 'ble/util/print [; ble/function#advice/do; ble/util/print ]'
   1368   ble/test f1 stdout={A,[,original,],B}
   1369 
   1370   ble/function#advice around f1 '
   1371     ADVICE_WORDS[1]=quick
   1372     ble/util/print [; ble/function#advice/do; ble/util/print ]
   1373     ADVICE_EXIT=99'
   1374   ble/test f1 stdout={A,[,'original quick',],B} exit=99
   1375   
   1376   ble/function#advice remove f1
   1377   ble/test f1 stdout='original' exit=0
   1378   ble/test 'f1 1' stdout='original 1' exit=0
   1379 )
   1380 
   1381 # ble/function#{push,pop}
   1382 (
   1383   ble/test 'echo 1 2 3' stdout='1 2 3'
   1384   ble/test 'ble/is-function echo' exit=1
   1385   ble/function#push echo 'builtin echo "[$*]"'
   1386   ble/test 'ble/is-function echo'
   1387   ble/test 'echo 1 2 3' stdout='[1 2 3]'
   1388   ble/function#push echo 'builtin echo "($*)"'
   1389   ble/test 'echo 1 2 3' stdout='(1 2 3)'
   1390   ble/function#push echo 'builtin echo A; ble/function#push/call-top "$@"; builtin echo Z'
   1391   ble/test 'echo 1 2 3' stdout={A,'(1 2 3)',Z}
   1392   ble/function#push echo 'builtin echo [; ble/function#push/call-top "$@"; builtin echo ]'
   1393   ble/test 'echo 1 2 3' stdout={[,A,'(1 2 3)',Z,]}
   1394 
   1395   ble/test 'ble/function#pop echo'
   1396   ble/test 'echo 1 2 3' stdout={A,'(1 2 3)',Z}
   1397   ble/function#pop echo
   1398   ble/test 'echo 1 2 3' stdout='(1 2 3)'
   1399   ble/function#pop echo
   1400   ble/test 'echo 1 2 3' stdout='[1 2 3]'
   1401   ble/test 'ble/is-function echo'
   1402   ble/test 'ble/function#pop echo'
   1403   ble/test 'ble/is-function echo' exit=1
   1404   ble/test 'echo 1 2 3' stdout='1 2 3'
   1405   ble/test 'ble/function#pop echo' exit=1
   1406   ble/test 'echo 1 2 3' stdout='1 2 3'
   1407 )
   1408 
   1409 # ToDo
   1410 # ble/function#evaldef
   1411 # ble/function#trace
   1412 # ble/function#has-trace
   1413 # ble/function#has-attr
   1414 # ble/function/is-global-trace-context
   1415 # ble/function#get-source-and-lineno
   1416 # ble/function#lambda
   1417 # ble/function#suppress-stderr
   1418 
   1419 # ble/util/set
   1420 (
   1421   ble/test 'ble/util/set ret hello' ret='hello'
   1422   ble/test 'ble/util/set ret "hello world"' ret='hello world'
   1423   ble/test 'ble/util/set ret ""' ret=''
   1424   ble/test 'ble/util/set ret " "' ret=' '
   1425   ble/test 'ble/util/set ret " a"' ret=' a'
   1426   ble/test 'ble/util/set ret "a "' ret='a '
   1427   ble/test 'ble/util/set ret $'\''\n'\''' ret=$'\n'
   1428   ble/test 'ble/util/set ret A$'\''\n'\''' ret=A$'\n'
   1429   ble/test 'ble/util/set ret A$'\''\n'\''B' ret=A$'\n'B
   1430 )
   1431 
   1432 # ble/util/sprintf
   1433 (
   1434   ble/test 'ble/util/sprintf ret "[%s]" 1 2 3' ret='[1][2][3]'
   1435   ble/test 'ble/util/sprintf ret "[%5s]" 1' ret='[    1]'
   1436   ble/test 'ble/util/sprintf ret "[%.2s]" 12345' ret='[12]'
   1437   ble/test 'ble/util/sprintf ret "[%d,%d]" 1 3' ret='[1,3]'
   1438   ble/test 'ble/util/sprintf ret "[%x]" 27' ret='[1b]'
   1439   ble/test 'ble/util/sprintf ret "[%#.2g]" 27' ret='[27.]'
   1440   ble/test 'ble/util/sprintf ret "[%#.2f]" 27' ret='[27.00]'
   1441 )
   1442 
   1443 # ble/util/type
   1444 (
   1445   shopt -s expand_aliases
   1446   alias aaa=fun
   1447   function fun { :; }
   1448   function ble/fun { :; }
   1449   function ble/fun:type { :; }
   1450   function ble/fun#meth { :; }
   1451 
   1452   ble/test 'ble/util/type ret aaa' ret=alias
   1453   ble/test 'ble/util/type ret fun' ret=function
   1454   ble/test 'ble/util/type ret alias' ret=builtin
   1455   ble/test 'ble/util/type ret mkfifo' ret=file
   1456   ble/test 'ble/util/type ret for' ret=keyword
   1457   ble/test 'ble/util/type ret ble/fun' ret=function
   1458   ble/test 'ble/util/type ret ble/fun:type' ret=function
   1459   ble/test 'ble/util/type ret ble/fun#meth' ret=function
   1460 
   1461   ble/test 'ble/util/type ret fun1' ret=
   1462   ble/test 'ble/util/type ret ble/fun1' ret=
   1463   ble/test 'ble/util/type ret ble/fun1:type' ret=
   1464   ble/test 'ble/util/type ret ble/fun1#meth' ret=
   1465 )
   1466 
   1467 # ToDo
   1468 # ble/is-alias
   1469 # ble/alias/list
   1470 # ble/alias#active
   1471 
   1472 # ble/alias#expand
   1473 (
   1474   shopt -s expand_aliases
   1475 
   1476   # Note: 複数段階の展開は実行しない
   1477   alias aaa1='aaa2 world'
   1478   ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
   1479   alias aaa2='aaa3 hello'
   1480   ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
   1481   ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
   1482   alias aaa3='aaa4'
   1483   ble/test 'ble/alias#expand aaa3' ret='aaa4'
   1484   ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
   1485   ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
   1486   alias aaa4='echo'
   1487   ble/test 'ble/alias#expand aaa4' ret='echo'
   1488   ble/test 'ble/alias#expand aaa3' ret='aaa4'
   1489   ble/test 'ble/alias#expand aaa2' ret='aaa3 hello'
   1490   ble/test 'ble/alias#expand aaa1' ret='aaa2 world'
   1491 )
   1492 
   1493 # ble/util/is-stdin-ready
   1494 if ((_ble_bash>=40000)); then
   1495   (
   1496     ble/test 'echo 1 | { sleep 0.01; ble/util/is-stdin-ready; }'
   1497     [[ ${CI-} == true && ${GITHUB_ACTION-} && $OSTYPE == msys* ]] ||
   1498       ble/test 'sleep 0.01 | ble/util/is-stdin-ready' exit=1
   1499     ble/test 'ble/util/is-stdin-ready <<< a'
   1500     ble/test 'ble/util/is-stdin-ready <<< ""'
   1501 
   1502     # EOF は成功してしまう? これは意図しない振る舞いである。
   1503     # しかし bash 自体が終了するので関係ないのかもしれない。
   1504     ble/test ': | { sleep 0.01; ble/util/is-stdin-ready; }'
   1505     ble/test 'ble/util/is-stdin-ready < /dev/null'
   1506   )
   1507 fi
   1508 
   1509 # ble/util/is-running-in-subshell
   1510 ble/test ble/util/is-running-in-subshell exit=1
   1511 ( ble/test ble/util/is-running-in-subshell )
   1512 
   1513 # ble/util/getpid
   1514 (
   1515   ble/test/chdir
   1516   function getpid {
   1517     sh -c 'printf %s $PPID' >| a.txt
   1518     ble/util/readfile ppid a.txt
   1519   }
   1520 
   1521   dummy=modification_to_environment.1
   1522   ble/util/getpid
   1523   ble/test '[[ $BASHPID != $$ ]]'
   1524   getpid
   1525   ble/test code:'ret=$BASHPID' ret="$ppid"
   1526   pid1=$BASHPID
   1527   (
   1528     dummy=modification_to_environment.2
   1529     ble/util/getpid
   1530     ble/test '[[ $BASHPID != $$ && $BASHPID != $pid1 ]]'
   1531     getpid
   1532     ble/test '[[ $BASHPID == $ppid ]]'
   1533   )
   1534   ble/test/rmdir
   1535 )
   1536 
   1537 # ble/fd#is-open
   1538 (
   1539   ble/test 'ble/fd#is-open 1'
   1540   ble/test 'ble/fd#is-open 2'
   1541   exec 9>&-
   1542   ble/test 'ble/fd#is-open 9' exit=1
   1543   exec 9>/dev/null
   1544   ble/test 'ble/fd#is-open 9'
   1545   exec 9>&-
   1546   ble/test 'ble/fd#is-open 9' exit=1
   1547 )
   1548 
   1549 # ble/fd#alloc
   1550 # ble/fd#close
   1551 (
   1552   ble/test/chdir
   1553   ble/fd#alloc fd '> a.txt'
   1554   ble/util/print hello >&"$fd"
   1555   ble/util/print world >&"$fd"
   1556   if ((_ble_bash/100!=301)); then
   1557     # bash-3.1 はバグがあって一度開いた fd を閉じれない。
   1558     ble/test 'ble/fd#close fd; echo test >&"$fd"' exit=1
   1559     ble/test 'cat a.txt' stdout={hello,world}
   1560   fi
   1561   ble/test/rmdir
   1562 )
   1563 
   1564 # ble/util/declare-print-definitions
   1565 (
   1566   xv1=''
   1567   xv2a='a' xv2b='ab'
   1568   xv3a=' ' xv3b='a b'
   1569   xv4a=$'\n' xv4b=$'a\nb'
   1570   xv5a=$'\r' xv5b=$'a\rb'
   1571   xv6a=$'\x01' xv6b=a$'\x01'b
   1572   xv7a=$'\x02' xv7b=a$'\x02'b
   1573   xv8a=$'\x7F' xv8b=a$'\x7F'b
   1574   builtin eval -- "$(
   1575     for name in v1 v{2..8}{a,b}; do
   1576       builtin eval "$name=\$x$name"
   1577     done
   1578     ble/util/declare-print-definitions vn v1 v{2..8}{a,b} 2>/dev/null)"
   1579 
   1580   ble/test '[[ ! ${vn+set} ]]'
   1581   for name in v1 v{2..8}{a,b}; do
   1582     ble/test "declare -p $name x$name | cat -v >&2; [[ \$$name == \$x$name ]]"
   1583   done
   1584 
   1585   function status { builtin eval 'ret="${#'$1'[*]}:(""${'$1'[*]}"")"'; }
   1586   xa0=() sa0='0:()'
   1587   xa1=('') sa1='1:()'
   1588   for k in {2..8}; do
   1589     builtin eval "xa$k=(); xa$k[0]=\"\$xv${k}a\"; xa$k[1]=\"\$xv${k}b\""
   1590     builtin eval "sa$k=\"2:(\$xv${k}a \$xv${k}b)\""
   1591   done
   1592   builtin eval -- "$(
   1593     for name in a0 a1 a{2..8}; do
   1594       builtin eval "$name=(\"\${x$name[@]}\")"
   1595     done
   1596     ble/util/declare-print-definitions a0 a1 a{2..8} 2>/dev/null)"
   1597 
   1598   for name in a0 a1 a{2..8}; do
   1599     # WA: msys bash では何故か配列代入形式 arr2=("${arr1[@]}") で要素に含まれる
   1600     # \r が全て消滅する。仕方がないのでスキップする。
   1601     [[ $name == a5 && $OSTYPE == msys* ]] && continue
   1602 
   1603     stdout_var=s$name
   1604     ble/test "status $name" ret="${!stdout_var}"
   1605   done
   1606 )
   1607 
   1608 # ble/util/print-global-definitions
   1609 (
   1610   function status { builtin eval 'ble/util/print "${#'$1'[*]}:(""${'$1'[*]}"")"'; }
   1611   v1=123 v2=(1 2 3) v3=bbb v4=ccc
   1612   function f2 {
   1613     local v3=x v4=y
   1614     builtin eval -- "$(ble/util/print-global-definitions v{0..4})"
   1615     ble/test '[[ ! ${v0+set} ]]'
   1616     ble/test 'status v1' stdout='1:(123)'
   1617     ble/test 'status v2' stdout='3:(1 2 3)'
   1618     ble/test 'status v3' stdout='1:(bbb)'
   1619     ble/test 'status v4' stdout='1:(ccc)'
   1620   }
   1621   function f1 {
   1622     local v0=1 v1=2 v2=3 v4=5
   1623     f2
   1624     # 上のスコープには影響を与えない。
   1625     ble/test 'status v1' stdout='1:(2)'
   1626     ble/test 'status v2' stdout='1:(3)'
   1627   }
   1628   f1
   1629 
   1630   value="hello 'world'"
   1631   ble/test 'ble/util/print-global-definitions value' stdout="declare value='hello '\''world'\'''"
   1632 )
   1633 
   1634 # ble/util/has-glob-pattern
   1635 (
   1636   ble/test 'ble/util/has-glob-pattern "a*"'
   1637   ble/test 'ble/util/has-glob-pattern "a*b"'
   1638   ble/test 'ble/util/has-glob-pattern "?"'
   1639   ble/test 'ble/util/has-glob-pattern "a?"'
   1640   ble/test 'ble/util/has-glob-pattern "a?b"'
   1641   ble/test 'ble/util/has-glob-pattern "a?b*c"'
   1642   ble/test 'ble/util/has-glob-pattern "a[a-c]d"'
   1643   ble/test 'ble/util/has-glob-pattern "a[!a-c]d"'
   1644   ble/test 'ble/util/has-glob-pattern "*.txt"'
   1645   ble/test 'ble/util/has-glob-pattern "*.*"'
   1646 
   1647   ble/test 'ble/util/has-glob-pattern ""'    exit=1
   1648   ble/test 'ble/util/has-glob-pattern "a"'   exit=1
   1649   ble/test 'ble/util/has-glob-pattern "abc"' exit=1
   1650   ble/test 'ble/util/has-glob-pattern "/"'   exit=1
   1651   ble/test 'ble/util/has-glob-pattern "a/c"' exit=1
   1652   ble/test 'ble/util/has-glob-pattern "a:b"' exit=1
   1653   ble/test 'ble/util/has-glob-pattern "a=b"' exit=1
   1654 
   1655   # 以下は文脈によって異なる物。Bash-5.0 では var='\[xyz\]' として
   1656   # echo $var とするとパス名展開の対象となるが、
   1657   # それ以外ではパス名展開とは解釈されない。
   1658   ble/test 'ble/util/has-glob-pattern "\[xyz\]"' exit=1
   1659 )
   1660 
   1661 # ble/util/is-cygwin-slow-glob
   1662 # ble/util/eval-pathname-expansion
   1663 (
   1664   shopt -s failglob
   1665   shopt -s nullglob
   1666   shopt -s extglob
   1667   ble/util/eval-pathname-expansion 'non-existent-*-file' canonical
   1668   ble/test 'shopt -q failglob'
   1669   ble/test 'shopt -q nullglob'
   1670   ble/test 'shopt -q extglob'
   1671 )
   1672 # ble/util/isprint+
   1673 # ble/util/strftime
   1674 
   1675 # ble/util/{msleep,sleep}
   1676 if ! [[ ${CI-} == true && ${GITHUB_ACTION-} ]]; then
   1677   ble/util/msleep/.calibrate-loop &>/dev/null
   1678   ble/util/msleep/.calibrate-loop &>/dev/null
   1679   ble/util/msleep/.calibrate-loop &>/dev/null
   1680   (
   1681     ble/test 'ble-measure -q "ble/util/msleep 100"; echo "$ret usec" >&2; ((msec=ret/1000,90<=msec&&msec<=120))'
   1682     ble/test 'ble-measure -q "ble/util/sleep 0.1"; echo "$ret usec" >&2; ((msec=ret/1000,90<=msec&&msec<=120))'
   1683   )
   1684 fi
   1685 
   1686 # ble/util/conditional-sync
   1687 (
   1688   time=0
   1689   ble/function#push ble/util/msleep '((time+=$1));ble/util/print $time'
   1690   ble/test "ble/util/conditional-sync 'ble/bin/sleep 10' '((time<1000))' 100" \
   1691            stdout={1..10}00
   1692   ble/test "ble/util/conditional-sync 'ble/bin/sleep 10' '((time<1000))' 100 progressive-weight" \
   1693            stdout={1,3,7,15,31,63,{1..10}27}
   1694   ble/test "ble/util/conditional-sync 'ble/bin/sleep 10' 'true' 100 timeout=10" stdout=10 exit=142
   1695   ble/test "ble/util/conditional-sync 'echo unexpected' 'true' 100 timeout=0" stdout= exit=142
   1696   ble/bin/sleep 10 & pid1=$!
   1697   ble/test "ble/util/conditional-sync 'echo unexpected' 'true' 100 timeout=0:pid=$pid1" stdout= exit=142
   1698   ble/bin/sleep 10 & pid2=$!
   1699   ble/test "ble/util/conditional-sync 'echo unexpected' 'true' 100 timeout=-1:pid=$pid2" stdout= exit=142
   1700   set -m; ble/bin/sleep 10 & pid3=$!; set +m
   1701   ble/test "ble/util/conditional-sync 'echo unexpected' 'true' 100 timeout=0:pid=-$pid3" stdout= exit=142
   1702 
   1703   # wait for the signal processing for a short moment
   1704   if [[ $OSTYPE == cygwin* || $OSTYPE == msys* ]]; then
   1705     ble/bin/sleep 0.20
   1706   else
   1707     ble/bin/sleep 0.02
   1708   fi
   1709   ble/test 'kill -0 "$pid1"' exit=1
   1710   ble/test 'kill -0 "$pid2"' exit=1
   1711   ble/test 'kill -0 "$pid3"' exit=1
   1712   ble/function#pop ble/util/msleep
   1713 )
   1714 
   1715 # ble/util/cat
   1716 (
   1717   function ble/test:ble/util/cat { { ble/util/cat; ble/util/print x; } | cat -v; }
   1718   ble/test ":| ble/test:ble/util/cat"                       stdout=x
   1719   ble/test "printf a | ble/test:ble/util/cat"               stdout=ax
   1720   ble/test "printf '\0' | ble/test:ble/util/cat"            stdout=^@x
   1721   ble/test "printf 'hello\nworld\n'| ble/test:ble/util/cat" stdout={hello,world,x}
   1722   ble/test "printf 'hello\nworld'| ble/test:ble/util/cat"   stdout={hello,worldx}
   1723   ble/test "printf 'hello\0world\0'| ble/test:ble/util/cat" stdout=hello^@world^@x
   1724   ble/test "printf 'hello\0world'| ble/test:ble/util/cat"   stdout=hello^@worldx
   1725 )
   1726 
   1727 # ble/util/get-pager
   1728 (
   1729   bleopt_pager=xxx PAGER=yyy
   1730   ble/test 'ble/util/get-pager ret' ret=xxx
   1731   bleopt_pager=xxx PAGER=
   1732   ble/test 'ble/util/get-pager ret' ret=xxx
   1733   bleopt_pager= PAGER=yyy
   1734   ble/test 'ble/util/get-pager ret' ret=yyy
   1735   bleopt_pager= PAGER=
   1736   ble/test 'ble/util/get-pager ret' ret=less
   1737 )
   1738 
   1739 # ble/util/pager
   1740 (
   1741   bleopt_pager=cat
   1742   ble/test 'ble/util/pager <<< hello' stdout=hello
   1743 )
   1744 
   1745 
   1746 # # ble/file#mtime
   1747 # (
   1748 #   ble/file#mtime a
   1749 #   ble/test 'ble/string#match "$ret" "^[0-9]+\$"'
   1750 # )
   1751 
   1752 # ble/util/buffer
   1753 (
   1754   ble/util/buffer.clear
   1755   ble/test 'ble/util/buffer.flush' stdout=
   1756   ble/util/buffer hello
   1757   ble/util/buffer world
   1758   ble/test 'ble/util/buffer.flush' stdout=helloworld
   1759   ble/test 'ble/util/buffer.flush' stdout=
   1760   ble/util/buffer.print hello
   1761   ble/util/buffer.print world
   1762   ble/test 'ble/util/buffer.flush' stdout={hello,world}
   1763   ble/test 'ble/util/buffer.flush' stdout=
   1764   ble/util/buffer.print hello
   1765   ble/util/buffer.print world
   1766   ble/util/buffer.clear
   1767   ble/test 'ble/util/buffer.flush' stdout=
   1768 )
   1769 
   1770 # ble/dirty-range#{load,clear,update}
   1771 (
   1772   # ref #D0229 #D0134
   1773   ubeg=3 uend=10 uend0=5
   1774   beg=0 end=5 end0=3
   1775   ble/dirty-range#load --prefix=u
   1776   ble/test 'echo "$beg:$end:$end0"' stdout=3:10:5
   1777 
   1778   ubeg=3 uend=10 uend0=5
   1779   ble/dirty-range#clear --prefix=u
   1780   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=-1:-1:-1
   1781 
   1782   ble/dirty-range#update --prefix=u 0 5 2
   1783   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=0:5:2
   1784   ble/dirty-range#update --prefix=u 10 10 12
   1785   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=0:10:9
   1786 
   1787   ble/dirty-range#clear --prefix=u
   1788   ble/dirty-range#update --prefix=u 2 2 3
   1789   ble/dirty-range#update --prefix=u 2 2 3
   1790   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=2:2:4
   1791 
   1792   # (1) str3 = A0 [A1] A2 |     X      |     C
   1793   ble/dirty-range#clear --prefix=u
   1794   ble/dirty-range#update --prefix=u 1 5 3
   1795   ble/dirty-range#update --prefix=u 7 11 9
   1796   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=1:11:7
   1797 
   1798   # (2) str3 = A0 [A1     | X0]     X1 |     C
   1799   ble/dirty-range#clear --prefix=u
   1800   ble/dirty-range#update --prefix=u 1 7 5
   1801   ble/dirty-range#update --prefix=u 4 15 11
   1802   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=1:15:9
   1803 
   1804   # (3) str3 = A0 [A1     |     X      | C0] C1
   1805   ble/dirty-range#clear --prefix=u
   1806   ble/dirty-range#update --prefix=u 1 7 5
   1807   ble/dirty-range#update --prefix=u 3 4 5
   1808   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=1:6:5
   1809 
   1810   # (4) str3 = A          | X0 [X1] X2 |     C
   1811   ble/dirty-range#clear --prefix=u
   1812   ble/dirty-range#update --prefix=u 4 8 6
   1813   ble/dirty-range#update --prefix=u 2 8 10
   1814   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=2:8:8
   1815 
   1816   # (5) str3 = A          | X0     [X1 | C0] C1
   1817   ble/dirty-range#clear --prefix=u
   1818   ble/dirty-range#update --prefix=u 6 12 8
   1819   ble/dirty-range#update --prefix=u 3 7 8
   1820   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=3:11:8
   1821 
   1822   # (6) str3 = A          |     X      | C0 [C1] C2
   1823   ble/dirty-range#clear --prefix=u
   1824   ble/dirty-range#update --prefix=u 10 13 11
   1825   ble/dirty-range#update --prefix=u 3 7 8
   1826   ble/test 'echo "$ubeg:$uend:$uend0"' stdout=3:12:11
   1827 )
   1828 
   1829 # ToDo (update 2022-09-26)
   1830 # ble/file#hash
   1831 # ble/urange#{clear,update}
   1832 # ble/urange#shift
   1833 # ble/util/joblist
   1834 # ble/util/joblist.split
   1835 # ble/util/joblist.check
   1836 # ble/util/joblist.has-events
   1837 # ble/util/joblist.flush
   1838 # ble/util/joblist.bflush
   1839 # ble/util/joblist.clear
   1840 # ble/util/save-editing-mode
   1841 # ble/util/restore-editing-mode
   1842 # ble/util/reset-keymap-of-editing-mode
   1843 # ble/util/rlvar#load
   1844 # ble/util/rlvar#has
   1845 # ble/util/rlvar#test
   1846 # ble/util/rlvar#read
   1847 # ble/util/rlvar#bind-bleopt
   1848 # ble/util/invoke-hook
   1849 # ble/util/autoload
   1850 # ble-autoload
   1851 # ble/util/import/search
   1852 # ble/util/import/encode-filename
   1853 # ble/util/import/is-loaded
   1854 # ble/util/import/finalize
   1855 # ble/util/import/option:query
   1856 # ble/util/import/eval-after-load
   1857 # ble/util/import
   1858 # ble-import
   1859 # ble/util/stackdump
   1860 # ble-stackdump
   1861 # ble/util/assert
   1862 # ble-assert
   1863 # ble/util/clock
   1864 # ble/util/idle.do
   1865 # ble/util/idle/IS_IDLE
   1866 # ble/util/idle.push
   1867 # ble/util/idle.push-background
   1868 # ble/util/idle.sleep
   1869 # ble/util/idle.isleep
   1870 # ble/util/idle.sleep-until
   1871 # ble/util/idle.isleep-until
   1872 # ble/util/idle.wait-user-input
   1873 # ble/util/idle.wait-file-content
   1874 # ble/util/idle.wait-filename
   1875 # ble/util/idle.wait-condition
   1876 # ble/util/idle.continue
   1877 # ble/util/idle.cancel
   1878 # ble/util/idle.suspend
   1879 # ble/util/is-running-in-idle
   1880 # ble/util/fiberchain#initialize
   1881 # ble/util/fiberchain#resume
   1882 # ble/util/fiberchain#push
   1883 # ble/util/fiberchain#clear
   1884 # ble/term/put
   1885 # ble/term/cup
   1886 # ble/term/flush
   1887 # ble/term/audible-bell
   1888 # ble/term/visible-bell
   1889 # ble/term/visible-bell:term/init
   1890 # ble/term/visible-bell:term/show
   1891 # ble/term/visible-bell:term/update
   1892 # ble/term/visible-bell:term/clear
   1893 # ble/term/visible-bell:canvas/init
   1894 # ble/term/visible-bell:canvas/show
   1895 # ble/term/visible-bell:canvas/update
   1896 # ble/term/visible-bell:canvas/clear
   1897 # ble/term/visible-bell/cancel-erasure
   1898 # ble/term/visible-bell/erase
   1899 # ble/term/stty/initialize
   1900 # ble/term/stty/leave
   1901 # ble/term/stty/enter
   1902 # ble/term/stty/finalize
   1903 # ble/term/stty/TRAPEXIT
   1904 # ble/term/cursor-state/hide
   1905 # ble/term/cursor-state/reveal
   1906 # ble/term/bracketed-paste-mode/enter
   1907 # ble/term/bracketed-paste-mode/leave
   1908 # ble/term/DA1/notify
   1909 # ble/term/DA2/notify
   1910 # ble/term/CPR/request.buff
   1911 # ble/term/CPR/request.draw
   1912 # ble/term/CPR/notify
   1913 # ble/term/modifyOtherKeys/enter
   1914 # ble/term/modifyOtherKeys/leave
   1915 # ble/term/modifyOtherKeys/reset
   1916 # ble/term/enter-altscr
   1917 # ble/term/leave-altscr
   1918 # ble/term/rl-convert-meta/enter
   1919 # ble/term/rl-convert-meta/leave
   1920 # ble/term/enter-for-widget
   1921 # ble/term/leave-for-widget
   1922 # ble/term/enter
   1923 # ble/term/leave
   1924 # ble/term/initialize
   1925 # ble/term/finalize
   1926 
   1927 # ble/util/{s2c,c2s}
   1928 (
   1929   ble/test $'ble/util/s2c "\n"' ret=10
   1930   ble/test 'ble/util/c2s 10' ret=$'\n'
   1931   ble/test $'ble/util/s2c "\x1b"' ret=27
   1932   ble/test 'ble/util/c2s 27' ret=$'\x1b'
   1933   ble/test $'ble/util/s2c "\x1F"' ret=31
   1934   ble/test 'ble/util/c2s 31' ret=$'\x1F'
   1935   c=$'\x7F' ble/test 'ble/util/s2c $c' ret=127 # bash-3.0 bug WA
   1936   ble/test 'ble/util/c2s 127' ret=$'\x7F'
   1937   ble/test 'ble/util/s2c " "' ret=32
   1938   ble/test 'ble/util/c2s 32' ret=' '
   1939   ble/test 'ble/util/s2c a' ret=97
   1940   ble/test 'ble/util/c2s 97' ret=a
   1941   ble/test 'ble/util/s2c μ' ret=956
   1942   ble/test 'ble/util/c2s 956' ret=μ
   1943   ble/test 'ble/util/s2c あ' ret=12354
   1944   ble/test 'ble/util/c2s 12354' ret=あ
   1945 
   1946   ble/test 'ble/util/s2c' ret=0
   1947   ble/test 'ble/util/s2c abc' ret=97
   1948   ble/test 'ble/util/s2c μν' ret=956
   1949   ble/test 'ble/util/s2c あいう' ret=12354
   1950 
   1951   ble/test 'ble/util/c2s.cached 32' ret=' '
   1952   ble/test 'ble/util/c2s.cached 97' ret=a
   1953   ble/test 'ble/util/c2s.cached 956' ret=μ
   1954   ble/test 'ble/util/c2s.cached 12354' ret=あ
   1955 
   1956   LC_ALL=C
   1957   ble/test 'ble/util/c2s 97' ret=a
   1958   ble/test 'ble/util/c2s 956; [[ $ret != μ ]]'
   1959   ble/test 'ble/util/c2s 12354; [[ $ret != あ ]]'
   1960 )
   1961 
   1962 # ble/util/c2bc
   1963 (
   1964   ble/test 'ble/util/c2bc 97' ret=1
   1965   ble/test 'ble/util/c2bc 956' ret=2
   1966   ble/test 'ble/util/c2bc 12354' ret=3
   1967 
   1968   ble/test 'ble/util/c2bc 0' ret=1
   1969   ble/test 'ble/util/c2bc 127' ret=1
   1970   ble/test 'ble/util/c2bc 128' ret=2
   1971   ble/test 'ble/util/c2bc 2047' ret=2
   1972   ble/test 'ble/util/c2bc 2048' ret=3
   1973   ble/test 'ble/util/c2bc 65535' ret=3
   1974   ble/test 'ble/util/c2bc 65536' ret=4
   1975 )
   1976 
   1977 # ble/util/{chars2s,s2chars}
   1978 (
   1979   ble/test 'ble/util/s2chars AaBbCc; ret="${ret[*]}"' ret='65 97 66 98 67 99'
   1980   ble/test 'ble/util/chars2s 65 97 66 98 67 99' ret=AaBbCc
   1981   ble/test 'ble/util/s2chars あいう; ret="${ret[*]}"' ret='12354 12356 12358'
   1982   ble/test 'ble/util/chars2s 12354 12356 12358' ret=あいう
   1983 
   1984   ble/test 'ble/util/s2chars; ret="${ret[*]}"' ret=
   1985   ble/test 'ble/util/s2chars 0; ret="${ret[*]}"' ret=48
   1986   ble/test 'ble/util/s2chars a; ret="${ret[*]}"' ret=97
   1987   ble/test 'ble/util/s2chars μ; ret="${ret[*]}"' ret=956
   1988   ble/test 'ble/util/s2chars あ; ret="${ret[*]}"' ret=12354
   1989   ble/test 'ble/util/chars2s' ret=
   1990   ble/test 'ble/util/chars2s 48' ret=0
   1991   ble/test 'ble/util/chars2s 97' ret=a
   1992   ble/test 'ble/util/chars2s 956' ret=μ
   1993   ble/test 'ble/util/chars2s 12354' ret=あ
   1994 )
   1995 
   1996 # ToDo: ble/util/s2bytes
   1997 
   1998 # ble/util/{c2keyseq,chars2keyseq,keyseq2chars}
   1999 (
   2000   function check1 {
   2001     local char=$1 keyseq=$2
   2002     ble/test "ble/util/c2keyseq $char" ret="$keyseq"
   2003     ble/test "ble/util/chars2keyseq $char" ret="$keyseq"
   2004     ble/test "ble/util/keyseq2chars '$keyseq'; ret=\"\${ret[*]}\"" ret="${3:-$char}"
   2005     ble/test "ble/util/chars2keyseq 98 $char 99" ret="b${keyseq}c"
   2006     ble/test "ble/util/keyseq2chars 'b${keyseq}c'; ret=\"\${ret[*]}\"" ret="98 ${3:-$char} 99"
   2007   }
   2008   check1 '7'   '\a' 
   2009   check1 '8'   '\b' 
   2010   check1 '9'   '\t' 
   2011   check1 '10'  '\n' 
   2012   check1 '11'  '\v' 
   2013   check1 '12'  '\f' 
   2014   check1 '13'  '\r' 
   2015   check1 '27'  '\e' 
   2016   check1 '127' '\d'
   2017   check1 '92'  '\\'   
   2018   check1 '28'  '\x1c' # workaround bashbug \C-\, \C-\\
   2019   check1 '156' '\x9c' # workaround bashbug \C-\, \C-\\
   2020 
   2021   check1 '0'   '\C-@'
   2022   check1 '1'   '\C-a'
   2023   check1 '26'  '\C-z'
   2024   check1 '29'  '\C-]'
   2025   check1 '30'  '\C-^'
   2026   check1 '31'  '\C-_'
   2027   check1 '128' '\M-\C-@' '27 0'
   2028 
   2029   check1 '64'    '@'
   2030   check1 '97'    'a'
   2031   check1 '956'   'μ'
   2032   check1 '12354' 'あ'
   2033 
   2034   ble/test ble/util/c2keyseq ret='\C-@'
   2035   ble/test ble/util/chars2keyseq ret=
   2036   ble/test ble/util/keyseq2chars ret=
   2037 )
   2038 
   2039 # ble/encoding:UTF-8/{b2c,c2b}
   2040 (
   2041   function pack { ret="${bytes[*]}"; }
   2042   ble/test 'ble/encoding:UTF-8/b2c    ' ret=0
   2043   ble/test 'ble/encoding:UTF-8/b2c  97' ret=97
   2044   ble/test 'ble/encoding:UTF-8/b2c  97  98  99 99' ret=97
   2045   ble/test 'ble/encoding:UTF-8/b2c 206 188  99 99' ret=956
   2046   ble/test 'ble/encoding:UTF-8/b2c 227 129 130 99' ret=12354
   2047 
   2048   ble/test 'ble/encoding:UTF-8/c2b 97   ; pack' ret=97
   2049   ble/test 'ble/encoding:UTF-8/c2b 956  ; pack' ret='206 188'
   2050   ble/test 'ble/encoding:UTF-8/c2b 12354; pack' ret='227 129 130'
   2051 
   2052   ble/test 'ble/encoding:UTF-8/c2b     ; pack' ret=0
   2053   ble/test 'ble/encoding:UTF-8/c2b 0   ; pack' ret=0
   2054   ble/test 'ble/encoding:UTF-8/c2b 127 ; pack' ret=127
   2055   ble/test 'ble/encoding:UTF-8/c2b 128 ; pack' ret='194 128'
   2056   ble/test 'ble/encoding:UTF-8/c2b 2047; pack' ret='223 191'
   2057   ble/test 'ble/encoding:UTF-8/c2b 2048; pack' ret='224 160 128'
   2058 )
   2059 
   2060 # ble/encoding:C/{b2c,c2b}
   2061 (
   2062   function pack { ret="${bytes[*]}"; }
   2063   ble/test 'ble/encoding:C/b2c    ' ret=0
   2064   ble/test 'ble/encoding:C/b2c  97' ret=97
   2065   ble/test 'ble/encoding:C/b2c  97  98  99 99' ret=97
   2066   ble/test 'ble/encoding:C/b2c 206 188  99 99' ret=206
   2067   ble/test 'ble/encoding:C/b2c 227 129 130 99' ret=227
   2068 
   2069   ble/test 'ble/encoding:C/b2c 97    ' ret=97
   2070   ble/test 'ble/encoding:C/b2c 956   ' ret=188
   2071   ble/test 'ble/encoding:C/b2c 12354 ' ret=66
   2072 
   2073   ble/test 'ble/encoding:C/c2b     ; pack' ret=0
   2074   ble/test 'ble/encoding:C/c2b 0   ; pack' ret=0
   2075   ble/test 'ble/encoding:C/c2b 127 ; pack' ret=127
   2076   ble/test 'ble/encoding:C/c2b 128 ; pack' ret=128
   2077   ble/test 'ble/encoding:C/c2b 2047; pack' ret=255
   2078   ble/test 'ble/encoding:C/c2b 2048; pack' ret=0
   2079 )
   2080 
   2081 # ble/util/is-unicode-output
   2082 (
   2083   function clear-locale { LC_ALL= LANG= LC_CTYPE=; }
   2084 
   2085   for lang in {C,en_US,ja{_JP,}}.{UTF-8,utf8} ja_JP.{utf8,UTF-8}@cjk{wide,narrow,single}; do
   2086     clear-locale
   2087     ble/test "LANG=$lang; ble/util/is-unicode-output"
   2088     clear-locale
   2089     ble/test "LANG=C LC_CTYPE=$lang; ble/util/is-unicode-output"
   2090     clear-locale
   2091     ble/test "LC_CTYPE=C LANG=C LC_ALL=$lang; ble/util/is-unicode-output"
   2092   done
   2093 
   2094   for lang in '' C POSIX UTF-8 utf8 ja_JP.eucJP; do
   2095     clear-locale
   2096     ble/test "LANG=$lang; ble/util/is-unicode-output" exit=1
   2097     clear-locale
   2098     ble/test "LANG=C LC_CTYPE=$lang; ble/util/is-unicode-output" exit=1
   2099     clear-locale
   2100     ble/test "LC_CTYPE=C LANG=C LC_ALL=$lang; ble/util/is-unicode-output" exit=1
   2101   done
   2102 )
   2103 
   2104 ble/test/end-section