diff --git a/NOTICE b/NOTICE index b09e672c7..7e0a0cfe8 100644 --- a/NOTICE +++ b/NOTICE @@ -58,6 +58,18 @@ Our jq builtin aims for compatibility with jq's query syntax and behavior. The implementation uses the jaq Rust crates (MIT licensed) rather than jq source code directly. +-------------------------------------------------------------------------------- +BashBox +-------------------------------------------------------------------------------- +Copyright (c) Pushpak Chhajed +Licensed under the MIT License + +Repository: https://github.com/shipfastlabs/bashbox + +The spec cases in crates/bashkit/tests/spec_cases/bash/bashbox-*.test.sh are +copied from BashBox's test suite (script and expected stdout, recorded from +GNU bash). The full MIT license text is in THIRD_PARTY_LICENSES/MIT.txt. + ================================================================================ RUST DEPENDENCIES ================================================================================ diff --git a/THIRD_PARTY_LICENSES/README.md b/THIRD_PARTY_LICENSES/README.md index 94ec3c991..bd1312bb8 100644 --- a/THIRD_PARTY_LICENSES/README.md +++ b/THIRD_PARTY_LICENSES/README.md @@ -27,7 +27,7 @@ Bashkit's design or whose test case formats have inspired our testing approach. | File | Projects | License Type | |------|----------|--------------| | `APACHE-2.0.txt` | just-bash, Oils | Apache License 2.0 | -| `MIT.txt` | jq, jaq crates, uutils coreutils, most dependencies | MIT License | +| `MIT.txt` | jq, jaq crates, uutils coreutils, BashBox spec cases, most dependencies | MIT License | | `LUCENT.txt` | One True AWK | Lucent Public License | ## Full Dependency Licenses diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-ansi-c-quoting.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-ansi-c-quoting.test.sh new file mode 100644 index 000000000..f3c466baa --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-ansi-c-quoting.test.sh @@ -0,0 +1,45 @@ +# BashBox ansi-c-quoting cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_ansi_c_quoting_the_result_is_quoted_text +# the result is quoted text +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=$'a\nb'; echo "$x"; echo "$'q'" '$'"'q'"; echo $"dq $x"; echo $'it\'s' $'a''b' x$'\t'y; touch zz; echo $'z'* $'*' +### expect +a +b +$'q' $'q' +dq a +b +it's ab x y +zz * +### end + +### bashbox_ansi_c_quoting_type_shows_it_single_quoted +# type shows it single-quoted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() { echo $'a\tb' $'it\'s' "$'x'" $"y"; } +type f +### expect +f is a function +f () +{ + echo 'a b' 'it'\''s' "$'x'" "y" +} +### end + +### bashbox_ansi_c_quoting_here_documents_expand_as_in_double_quotes_quotes_stay +# here-documents expand as in double quotes, quotes stay +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; cat <> 70 )) $(( 1 << -1 )) $(( 8 >> -62 )); z=1; ((z <<= 65)); echo $z +### expect +0 -420491770248316829 -9223372036854775808 1 1 -9223372036854775808 -1 -9223372036854775808 2 +2 +### end + +### bashbox_arithmetic_array_let_stops_at_a_failing_expression +# let stops at a failing expression +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +let "1/0" "y=2"; echo $? $y; let; echo $?; let x=1 "y=x+1"; echo $? $y; let 0; echo $? +### expect +1 +1 +0 2 +1 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-attributes.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-attributes.test.sh new file mode 100644 index 000000000..8c48436ab --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-attributes.test.sh @@ -0,0 +1,313 @@ +# BashBox attributes cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_attributes_a_plain_assignment_is_not_exported +# a plain assignment is not exported +FOO=1; printenv FOO; echo $? +### expect +1 +### end + +### bashbox_attributes_export_marks_the_name_so_later_values_reach_commands +# export marks the name, so later values reach commands +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export X=1; X=2; printenv X; export Y; Y=3; printenv Y +### expect +2 +3 +### end + +### bashbox_attributes_a_local_inherits_the_export_attribute +# a local inherits the export attribute +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export x=g; f(){ local x=1; printenv x; }; f +### expect +1 +### end + +### bashbox_attributes_local_x_exports_only_the_local +# local -x exports only the local +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=g; f(){ local -x x=1; printenv x; }; f; printenv x; echo $? +### expect +1 +1 +### end + +### bashbox_attributes_unset_drops_the_export_attribute +# unset drops the export attribute +export x=1; unset x; x=2; printenv x; echo $? +### expect +1 +### end + +### bashbox_attributes_export_n_un_exports +# export -n un-exports +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export A=1; export -n A; printenv A; echo $? $A +### expect +1 1 +### end + +### bashbox_attributes_declare_p_shows_r_and_x +# declare -p shows r and x +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -rx R=1; declare -p R; declare -x S; declare -p S; export -p | grep -w '[RS]' +### expect +declare -rx R="1" +declare -x S +declare -rx R="1" +declare -x S +### end + +### bashbox_attributes_declare_x_un_exports +# declare +x un-exports +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -x A=1; declare +x A; printenv A; echo $? +### expect +1 +### end + +### bashbox_attributes_set_a_exports_every_assignment_while_on +# set -a exports every assignment while on +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -a; B=2; printenv B; echo $-; set +a; C=3; printenv C; echo $? +### expect +2 +ahBc +1 +### end + +### bashbox_attributes_allexport_covers_locals_and_read_not_arrays +# allexport covers locals and read, not arrays +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -o allexport; f(){ local l=3; declare -p l; }; f; read r <<< hi; declare -p r; arr=(1); declare -p arr +### expect +declare -x l="3" +declare -x r="hi" +declare -a arr=([0]="1") +### end + +### bashbox_attributes_prefix_assignments_are_exported_for_one_command +# prefix assignments are exported for one command +FOO=1 printenv FOO; printenv FOO; echo $?; f(){ printenv V; }; V=7 f; printenv V; echo $? +### expect +1 +1 +7 +1 +### end + +### bashbox_attributes_a_prefix_assignment_to_an_exported_variable_restores_its_val +# a prefix assignment to an exported variable restores its value +export V=0; V=1 printenv V; printenv V +### expect +1 +0 +### end + +### bashbox_attributes_arrays_print_with_a_or_a_an_associative_one_with_a_trailing_ +# arrays print with a or A, an associative one with a trailing space +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -a arr=(1 2); export arr; declare -p arr; declare -A m=([k]=v); declare -p m +### expect +declare -ax arr=([0]="1" [1]="2") +declare -A m=([k]="v" ) +### end + +### bashbox_attributes_a_local_hides_a_until_the_function_returns +# a local hides -A until the function returns +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -A m=([a]=1); f(){ local m; declare -p m; local -A n; n[x]=1; declare -p n; }; f; declare -p m +### expect +declare -- m +declare -A n=([x]="1" ) +declare -A m=([a]="1" ) +### end + +### bashbox_attributes_declare_rejects_names_that_are_not_identifiers_and_options_a +# declare rejects names that are not identifiers, and options after the names +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare 1x=2 y=3 -z; echo $? $y +### expect +1 3 +### end + +### bashbox_attributes_local_rejects_names_that_are_not_identifiers +# local rejects names that are not identifiers +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ local a-b=1 c=2; echo $? $c; }; f +### expect +1 2 +### end + +### bashbox_attributes_readonly_rejects_names_that_are_not_identifiers +# readonly rejects names that are not identifiers +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly 9=1 r=1; echo $? $r; readonly | grep ' r=' +### expect +1 1 +declare -r r="1" +### end + +### bashbox_attributes_export_rejects_names_that_are_not_identifiers +# export rejects names that are not identifiers +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export a.b x=1; echo $?; printenv x +### expect +1 +1 +### end + +### bashbox_attributes_export_rejects_unknown_options +# export rejects unknown options +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export -z; echo $? +### expect +2 +### end + +### bashbox_attributes_declare_assigns_an_array_element +# declare assigns an array element +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare a[1]=x; declare -p a +### expect +declare -a a=([1]="x") +### end + +### bashbox_attributes_readonly_p_shows_each_variable_s_attributes +# readonly -p shows each variable's attributes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly U; export V; readonly V; readonly -p | grep -w '[UV]' +### expect +declare -r U +declare -rx V +### end + +### bashbox_attributes_declare_p_escapes_quotes_dollars_backquotes_and_backslashes +# declare -p escapes quotes, dollars, backquotes and backslashes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x='a"b$c`d\e'; declare -p x; a=("q\""); declare -p a +### expect +declare -- x="a\"b\$c\`d\\e" +declare -a a=([0]="q\"") +### end + +### bashbox_attributes_export_f_only_checks_that_the_functions_exist +# export -f only checks that the functions exist +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ :; }; export -f f; echo $?; export -f nosuch; echo $? +### expect +0 +1 +### end + +### bashbox_attributes_env_sees_only_exported_variables +# env sees only exported variables +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +env | grep -c FOO; FOO=1 env | grep FOO; export E=1; (E=2; printenv E); printenv E; x=$(printenv E); echo $x +### expect +0 +FOO=1 +2 +1 +1 +### end + +### bashbox_attributes_options_end_at +# options end at -- +export -- G=1; printenv G +### expect +1 +### end + +### bashbox_attributes_o_in_a_cluster_takes_the_next_argument_as_its_option_name +# o in a cluster takes the next argument as its option name +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -euo pipefail; echo "[${1-}]" $-; shopt -po pipefail +### expect +[] ehuBc +set -o pipefail +### end + +### bashbox_attributes_several_o_options +# several -o options +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -o errexit -o nounset; echo $-; set +o nounset; echo $- +### expect +ehuBc +ehBc +### end + +### bashbox_attributes_o_at_the_end_of_a_cluster_lists_the_options_after_applying_t +# o at the end of a cluster lists the options after applying the others +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -euo | grep -E '^(errexit|nounset|xtrace) ' +### expect +errexit on +nounset on +xtrace off +### end + +### bashbox_attributes_o_at_the_end_prints_them_as_commands +# +o at the end prints them as commands +set -e +o | grep -E 'errexit|pipefail' +### expect +set -o errexit +set +o pipefail +### end + +### bashbox_attributes_an_unknown_option_name_changes_nothing +# an unknown option name changes nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -o bogus -u; echo $? $- +### expect +2 hBc +### end + +### bashbox_attributes_an_unknown_letter_changes_nothing +# an unknown letter changes nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -ez; echo $? $- +### expect +2 hBc +### end + +### bashbox_attributes_a_bad_option_inside_is_reported_as +# a bad option inside -- is reported as - +set --bogus; echo $? +### expect +2 +### end + +### bashbox_attributes_letters_with_no_effect_here_are_accepted +# letters with no effect here are accepted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -hkB; echo $? +### expect +0 +### end + +### bashbox_attributes_words_after_the_options_become_positional_parameters +# words after the options become positional parameters +set -e a b; echo "$@"; set -ex -- c d; echo "$@" +### expect +a b +c d +### end + +### bashbox_attributes_with_nothing_after_it_clears_them +# -- with nothing after it clears them +set -- a b; set --; echo $# +### expect +0 +### end + +### bashbox_attributes_a_lone_keeps_them +# a lone - keeps them +set -- a b; set -; echo $# "$@"; set - c; echo "$@" +### expect +2 a b +c +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-base64.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-base64.test.sh new file mode 100644 index 000000000..3887babb1 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-base64.test.sh @@ -0,0 +1,10 @@ +# BashBox base64 cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_base64_empty_input_encodes_to_nothing +# empty input encodes to nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '' | base64 +### expect +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-cat.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-cat.test.sh new file mode 100644 index 000000000..2da16f3fe --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-cat.test.sh @@ -0,0 +1,56 @@ +# BashBox cat cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_cat_b_numbers_only_non_blank_lines_and_wins_over_n +# -b numbers only non-blank lines and wins over -n +printf 'a\n\nb\n' | cat -nb +### expect + 1 a + + 2 b +### end + +### bashbox_cat_s_squeezes_blank_runs_across_files +# -s squeezes blank runs across files +printf 'a\n\n' > c1; printf '\n\nb\n' > c2; cat -sn c1 c2 +### expect + 1 a + 2 + 3 b +### end + +### bashbox_cat_t_shows_tabs +# -T shows tabs +printf 'a\tb\n' | cat -T +### expect +a^Ib +### end + +### bashbox_cat_v_shows_control_and_high_bytes +# -v shows control and high bytes +printf 'a\t\001\177\200\211\240\377\n' | cat -v +### expect +a ^A^?M-^@M-^IM- M-^? +### end + +### bashbox_cat_a_is_vet +# -A is -vET +printf 'a\tb\r\n' | cat -A +### expect +a^Ib^M$ +### end + +### bashbox_cat_e_is_ve +# -e is -vE +printf '\ta\r\n' | cat -e +### expect + a^M$ +### end + +### bashbox_cat_t_is_vt +# -t is -vT +printf '\ta\r\n' | cat -t +### expect +^Ia^M +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-checksum.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-checksum.test.sh new file mode 100644 index 000000000..d340a1697 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-checksum.test.sh @@ -0,0 +1,30 @@ +# BashBox checksum cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_checksum_stdin +# stdin +printf 'hello\n' | md5sum +### expect +b1946ac92492d2347c6235b4d2611184 - +### end + +### bashbox_checksum_newline_in_name +# newline in name +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf z > $'n\nl'; md5sum $'n\nl' +### expect +\fbade9e36a3f36d3d676c1b808451dd7 n\nl +### end + +### bashbox_checksum_check_quiet +# check quiet +md5sum --quiet -c good.md5 +### expect +### end + +### bashbox_checksum_check_status_ok +# check status ok +md5sum --status -c good.md5 +### expect +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-chmod.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-chmod.test.sh new file mode 100644 index 000000000..57e662cb6 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-chmod.test.sh @@ -0,0 +1,9 @@ +# BashBox chmod cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_chmod_f_stays_quiet_but_still_fails +# -f stays quiet but still fails +chmod -f 644 nope; ln -s nope dl; chmod -f 644 dl +### expect +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-comm.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-comm.test.sh new file mode 100644 index 000000000..6d94cd6a7 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-comm.test.sh @@ -0,0 +1,24 @@ +# BashBox comm cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_comm_suppress_all +# suppress all +comm -123 a b +### expect +### end + +### bashbox_comm_zero_terminated +# zero terminated +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\0b\0' > z1; printf 'b\0c\0' > z2; comm -z z1 z2 | od -c +### expect +0000000 a \0 \t \t b \0 \t c \0 +0000011 +### end + +### bashbox_comm_empty_files +# empty files +printf '' > e; comm e e +### expect +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-compound-syntax.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-compound-syntax.test.sh new file mode 100644 index 000000000..ec666839c --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-compound-syntax.test.sh @@ -0,0 +1,74 @@ +# BashBox compound-syntax cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_compound_syntax_until_loop +# until loop +i=0; until (( i >= 3 )); do echo $i; i=$((i+1)); done +### expect +0 +1 +2 +### end + +### bashbox_compound_syntax_c_style_for +# c-style for +for ((i=0; i<6; i+=2)); do echo $i; done +### expect +0 +2 +4 +### end + +### bashbox_compound_syntax_case +# [[ && ( || ) ]] +[[ -n a && ( -z "" || x == y ) ]] && echo yes +### expect +yes +### end + +### bashbox_compound_syntax_case_2 +# [[ || ! ]] +[[ a == b || ! -n "" ]]; echo $?; [[ a == b || -z x ]]; echo $? +### expect +0 +1 +### end + +### bashbox_compound_syntax_bare_word +# [[ bare word ]] +[[ word ]] && echo set; [[ "" ]] || echo empty +### expect +set +empty +### end + +### bashbox_compound_syntax_quoted_and_escaped_parens_inside +# quoted and escaped parens inside $(...) +echo $(echo 'a)' "b)" \) ) +### expect +a) b) ) +### end + +### bashbox_compound_syntax_a_brace_inside_inside +# a brace inside $(...) inside ${...} +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo ${x:-$(echo })} +### expect +} +### end + +### bashbox_compound_syntax_quoted_and_escaped_braces_inside +# quoted and escaped braces inside ${...} +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +y=ab; echo ${x:-"}"} ${x:-\}} ${x:-'a}'} ${y/a/\}} "${y/b/'}'}" +### expect +} } a} }b a} +### end + +### bashbox_compound_syntax_single_quotes_stay_literal_in_a_double_quoted_default_word +# single quotes stay literal in a double-quoted default word +y=1; echo "${x:-'}'}" "${x:-"a b"}" "${x:-'a'"b"}" "${y:+'a'}" +### expect +'}' a b 'a'b 'a' +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-cut.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-cut.test.sh new file mode 100644 index 000000000..9bb3bccd0 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-cut.test.sh @@ -0,0 +1,31 @@ +# BashBox cut cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_cut_fields_with_a_delimiter +# fields with a delimiter +printf 'a:b:c:d\nnodelim\n' | cut -d: -f1,3- +### expect +a:c:d +nodelim +### end + +### bashbox_cut_fields_default_to_tab_delimited +# fields default to tab-delimited +printf 'a\tb\n' | cut -f2 +### expect +b +### end + +### bashbox_cut_separate_delimiter_argument_and_open_start_range +# separate delimiter argument and open start range +echo a:b:c | cut -d : -f -2 +### expect +a:b +### end + +### bashbox_cut_empty_input +# empty input +printf '' | cut -f1 +### expect +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-date.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-date.test.sh new file mode 100644 index 000000000..0a00e27d3 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-date.test.sh @@ -0,0 +1,26 @@ +# BashBox date cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_date_default_format +# default format +date -u -d @0 +### expect +Thu Jan 1 00:00:00 UTC 1970 +### end + +### bashbox_date_combined_ud +# combined -ud +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +date -ud @86400; date -ud@86400 +%F +### expect +Fri Jan 2 00:00:00 UTC 1970 +1970-01-02 +### end + +### bashbox_date_parses_date_strings +# parses date strings +date -u -d '2024-02-29 13:05:09' '+%j %H:%M:%S' +### expect +060 13:05:09 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-declare.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-declare.test.sh new file mode 100644 index 000000000..1d2b1da2f --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-declare.test.sh @@ -0,0 +1,414 @@ +# BashBox declare cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_declare_i_evaluates_each_assignment_and_adds +# -i evaluates each assignment, and += adds +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -i x=1+2; x+=3; echo $x; x='2*3'; echo $x; x=abc; echo $x; x=; echo $x; declare -p x +### expect +6 +6 +0 +0 +declare -i x="0" +### end + +### bashbox_declare_i_on_an_array_evaluates_each_element_as_it_is_assigned +# -i on an array evaluates each element as it is assigned +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -i a=(1+1 2*3); a+=(5+5); a[7]=3+3; a[7]+=1; declare -p a +### expect +declare -ai a=([0]="2" [1]="6" [2]="10" [7]="7") +### end + +### bashbox_declare_i_reads_and_let_agree +# -i reads and let/(( )) agree +declare -i x; let x=4; ((x=x+1)); echo $x; read x <<< 2+2; echo $x +### expect +5 +4 +### end + +### bashbox_declare_read_and_printf_name_themselves_too +# read and printf name themselves too +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -i x; (read x <<< 1/0); (printf -v x 1/0); echo $? +### expect +1 +### end + +### bashbox_declare_a_subshell_ends_with_status_1 +# a subshell ends with status 1 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +(declare -i x; x=1/0; echo in); echo out $? +### expect +out 1 +### end + +### bashbox_declare_i_removes_the_attribute_and_a_local_does_not_inherit_it +# +i removes the attribute, and a local does not inherit it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -i x=1; f() { local x; x=1+1; echo $x; }; f; declare +i x; x=1+1; echo $x +### expect +1+1 +1+1 +### end + +### bashbox_declare_a_prefix_assignment_ignores_i_l_and_u +# a prefix assignment ignores -i, -l and -u +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -u x; declare -i n; f() { echo "$x $n"; }; x=abc n=1/0 f +### expect +abc 1/0 +### end + +### bashbox_declare_l_and_u_convert_included +# -l and -u convert, += included +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -l x=ABC; x+=DEF; echo $x; declare -u y=abc; echo $y; read y <<< mixed; echo $y; declare -p x y +### expect +abcdef +ABC +MIXED +declare -l x="abcdef" +declare -u y="MIXED" +### end + +### bashbox_declare_l_and_u_replace_each_other_together_neither_changes +# -l and -u replace each other; together neither changes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -l x=AB; declare -u x; echo $x; x=Cd; echo $x; declare -lu x; x=eF; echo $x; declare +u x; x=Gh; declare -p x +### expect +ab +CD +eF +declare -- x="Gh" +### end + +### bashbox_declare_u_applies_to_array_elements +# -u applies to array elements +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -u a=(xa yb); a[3]=zz; a[3]+=q; declare -p a +### expect +declare -au a=([0]="XA" [1]="YB" [3]="ZZQ") +### end + +### bashbox_declare_declare_p_prints_the_attributes_in_bash_s_order +# declare -p prints the attributes in bash's order +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -ilrx x=5; declare -iAx m; declare -nr q=z; declare -p x m q +### expect +declare -irxl x="5" +declare -Aix m +declare -nr q="z" +### end + +### bashbox_declare_declared_but_unset_arrays_and_scalars_print_bare +# declared but unset arrays and scalars print bare +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -a e; declare -A f; declare -i g; declare -p e f g; e+=(q); declare -p e; [[ -v f ]]; echo $? +### expect +declare -a e +declare -A f +declare -i g +declare -a e=([0]="q") +1 +### end + +### bashbox_declare_a_scalar_declared_as_an_array_becomes_element_0 +# a scalar declared as an array becomes element 0 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; declare -A x; declare -p x; y=2; declare -a y; declare -p y; declare -a z=v; declare -p z +### expect +declare -A x=([0]="1" ) +declare -a y=([0]="2") +declare -a z=([0]="v") +### end + +### bashbox_declare_converting_between_indexed_and_associative_fails +# converting between indexed and associative fails +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1 2); declare -A a; echo $?; declare -A m; declare -a m; echo $?; declare -p a m +### expect +1 +1 +declare -a a=([0]="1" [1]="2") +declare -A m +### end + +### bashbox_declare_with_an_array_value_the_conversion_error_abandons_the_line +# with an array value the conversion error abandons the line +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1); declare -A a=([x]=2); echo same +echo next $?; declare -p a +### expect +next 1 +declare -a a=([0]="1") +### end + +### bashbox_declare_declare_with_only_attributes_lists_the_variables_that_have_t +# declare with only attributes lists the variables that have them all +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -i I=2; declare -ia J=(1); declare -A M; declare -ai; declare -A | grep ' M'; declare -i | grep -E '^declare -a?i [IJ]' +### expect +declare -ai J=([0]="1") +declare -A M +declare -i I="2" +declare -ai J=([0]="1") +### end + +### bashbox_declare_a_nameref_reads_writes_and_appends_through_to_its_target +# a nameref reads, writes and appends through to its target +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r=a; a=5; echo $r; r=7; echo $a; r+=x; echo $a; echo ${!r}; declare -p r a +### expect +5 +7 +7x +a +declare -n r="a" +declare -- a="7x" +### end + +### bashbox_declare_a_chain_of_namerefs +# a chain of namerefs +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r=x; declare -n s=r; s=5; echo $x ${!s} +### expect +5 x +### end + +### bashbox_declare_a_nameref_to_an_element +# a nameref to an element +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r=a[1]; r=x; echo $r; declare -p a +### expect +x +declare -a a=([1]="x") +### end + +### bashbox_declare_a_nameref_to_an_array +# a nameref to an array +declare -n r=arr; r=(1 2 3); echo ${r[1]} ${#r[@]} "${!r[@]}"; r[1]=b; declare -p arr +### expect +2 3 0 1 2 +declare -a arr=([0]="1" [1]="b" [2]="3") +### end + +### bashbox_declare_declare_acts_on_the_target_unless_n_is_given +# declare acts on the target unless -n is given +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r=x; declare r=5; declare -i r; r=1+1; declare -p r x +### expect +declare -n r="x" +declare -i x="2" +### end + +### bashbox_declare_n_turns_a_nameref_back_into_a_plain_variable +# +n turns a nameref back into a plain variable +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r=x; declare +n r; declare -p r +### expect +declare -- r="x" +### end + +### bashbox_declare_a_nameref_declared_without_a_value_takes_the_first_value_ass +# a nameref declared without a value takes the first value assigned +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r; r=x; declare -p r; echo "[${!r}]" +### expect +declare -n r="x" +[x] +### end + +### bashbox_declare_a_for_loop_points_a_nameref_at_each_word +# a for loop points a nameref at each word +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r; for r in a b; do r=v; done; declare -p a b r +### expect +declare -- a="v" +declare -- b="v" +declare -n r="b" +### end + +### bashbox_declare_local_n_refers_to_the_caller_s_variable +# local -n refers to the caller's variable +f() { local -n r=$1; r=hi; }; f v; echo $v +### expect +hi +### end + +### bashbox_declare_invalid_nameref_targets_are_refused +# invalid nameref targets are refused +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n r='1x'; echo $?; declare -n r=@; echo $?; f() { local -n r='a b'; }; f; echo $? +### expect +1 +1 +1 +### end + +### bashbox_declare_a_value_that_can_t_be_a_name_stays_and_declare_n_still_succe +# a value that can't be a name stays and declare -n still succeeds +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; declare -n x; echo $?; declare -p x; y=foo; declare -n y; declare -p y +### expect +1 +declare -- x="1" +declare -n y="foo" +### end + +### bashbox_declare_in_a_function_a_self_reference_only_warns +# in a function a self reference only warns +f() { local -n r=r; echo $?; }; f +### expect +0 +### end + +### bashbox_declare_a_circular_reference_reads_as_unset_with_a_warning +# a circular reference reads as unset with a warning +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n a=b; declare -n b=a; echo "${a-u}"; declare -p a b +### expect +u +declare -n a="b" +declare -n b="a" +### end + +### bashbox_declare_assigning_through_a_circular_reference_abandons_the_line +# assigning through a circular reference abandons the line +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n a=b; declare -n b=a; a=1; echo same +echo next $? +### expect +next 1 +### end + +### bashbox_declare_read_through_a_circular_reference_fails +# read through a circular reference fails +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -n a=b; declare -n b=a; read a <<< x; echo $? +### expect +1 +### end + +### bashbox_declare_a_nameref_local_to_a_function_is_restored +# a nameref local to a function is restored +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +r=global; f() { local -n r=x; r=1; }; f; echo $r $x +### expect +global 1 +### end + +### bashbox_declare_readonly_accepts_only_a_a_and_f +# readonly accepts only -a, -A and -f +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly -i r=1+1; echo $?; readonly -A m=([k]=v); declare -p m; readonly -a m2; declare -p m2 +### expect +2 +declare -Ar m=([k]="v" ) +declare -r m2 +### end + +### bashbox_declare_readonly_a_converts_nothing +# readonly -A converts nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1); readonly -A a; echo $?; declare -p a +### expect +0 +declare -ar a=([0]="1") +### end + +### bashbox_declare_export_and_readonly_assign_array_operands +# export and readonly assign array operands +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export a=(1 2); readonly b=(3); declare -p a b +### expect +declare -ax a=([0]="1" [1]="2") +declare -ar b=([0]="3") +### end + +### bashbox_declare_declare_p_quotes_control_characters_and_bytes_that_aren_t_ut +# declare -p quotes control characters and bytes that aren't UTF-8 like bash +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=$'a\x01b\e\'"\\c$`d\a\b\f\v\r\t\n\x7f'; declare -p x; y=$'\xc3\xa9\n'; z=$'\xff'; declare -p y z; a=($'x\ny' z); declare -p a +### expect +declare -- x=$'a\001b\E\'"\\c$`d\a\b\f\v\r\t\n\177' +declare -- y=$'é\n' +declare -- z=$'\377' +declare -a a=([0]=$'x\ny' [1]="z") +### end + +### bashbox_declare_associative_keys_with_shell_metacharacters_are_quoted +# associative keys with shell metacharacters are quoted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -A m=(["a b"]=1) n=(['$x']=2) o=([c]=3); declare -p m n o +### expect +declare -A m=(["a b"]="1" ) +declare -A n=(["\$x"]="2" ) +declare -A o=([c]="3" ) +### end + +### bashbox_declare_declare_p_with_no_names_lists_every_variable +# declare -p with no names lists every variable +unset PIPESTATUS; x=1; declare -p | grep -E '^declare -- x=' +### expect +declare -- x="1" +### end + +### bashbox_declare_plain_declare_lists_like_set +# plain declare lists like set +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; declare | grep '^x=' +### expect +x=1 +### end + +### bashbox_declare_printf_v_assigns_the_output_newlines_and_all +# printf -v assigns the output, newlines and all +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf -v x '%s-%s\n' a b; echo "[$x]"; printf -vy %s a; echo $y; printf -v 'a[1+1]' %s z; declare -p a +### expect +[a-b +] +a +declare -a a=([2]="z") +### end + +### bashbox_declare_printf_v_takes_and_a_local +# printf -v takes -- and a local +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf -v x -- %s a; echo $x; f() { local y; printf -v y %s in; echo $y; }; f; echo ${y-unset} +### expect +a +in +unset +### end + +### bashbox_declare_printf_v_errors +# printf -v errors +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf -v; echo $?; printf -v x; echo $? ${x-unset}; printf -v 1x %s a; echo $?; printf -v 'a[' %s x; echo $? +### expect +2 +2 unset +2 +2 +### end + +### bashbox_declare_printf_v_into_a_readonly_variable_fails +# printf -v into a readonly variable fails +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly r; printf -v r %s a; echo $? +### expect +1 +### end + +### bashbox_declare_printf_without_v_is_the_printf_command +# printf without -v is the printf command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf -- -v; echo +### expect +-v +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-du.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-du.test.sh new file mode 100644 index 000000000..9f6a6e998 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-du.test.sh @@ -0,0 +1,24 @@ +# BashBox du cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_du_human_rounding +# human rounding +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +for n in 1 1023 1024 1025 1536 10239 10240 10241 1047552 1047553 1048575 1048576 1048577 5000000; do printf "%${n}s" '' > f; du -bh f; done +### expect +1 f +1023 f +1.0K f +1.1K f +1.5K f +10K f +10K f +11K f +1023K f +1.0M f +1.0M f +1.0M f +1.1M f +4.8M f +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-echo.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-echo.test.sh new file mode 100644 index 000000000..4650cba79 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-echo.test.sh @@ -0,0 +1,66 @@ +# BashBox echo cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_echo_joins_arguments +# joins arguments +echo a b +### expect +a b +### end + +### bashbox_echo_escapes_are_literal_by_default +# escapes are literal by default +echo 'a\tb' +### expect +a\tb +### end + +### bashbox_echo_e_expands_escapes +# -e expands escapes +echo -e 'a\tb\\c\n' +### expect +a b\c + +### end + +### bashbox_echo_e_unknown_escape_and_trailing_backslash_stay +# -e unknown escape and trailing backslash stay +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo -e '\z\xg\' +### expect +\z\xg\ +### end + +### bashbox_echo_e_hex +# -e hex +echo -e '\x41\x4a2' +### expect +AJ2 +### end + +### bashbox_echo_e_c_stops_output_and_the_newline +# -e \c stops output and the newline +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo -e 'a\cb'; echo -e x +### expect +ax +### end + +### bashbox_echo_last_of_e_e_wins +# last of -e/-E wins +echo -eE 'a\tb'; echo -Ee 'a\tb' +### expect +a\tb +a b +### end + +### bashbox_echo_options_stop_at_the_first_non_option +# options stop at the first non-option +echo -nx; echo -- -n; echo -; echo a -n +### expect +-nx +-- -n +- +a -n +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-env-commands.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-env-commands.test.sh new file mode 100644 index 000000000..c7f5fb969 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-env-commands.test.sh @@ -0,0 +1,18 @@ +# BashBox env-commands cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_env_commands_i_starts_empty +# -i starts empty +env -i X=1; env - Y=2 +### expect +X=1 +Y=2 +### end + +### bashbox_env_commands_the_command_keeps_its_options_and_stdin +# the command keeps its options and stdin +echo hi | env -i cat -n +### expect + 1 hi +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-err-trap.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-err-trap.test.sh new file mode 100644 index 000000000..afc0282ad --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-err-trap.test.sh @@ -0,0 +1,189 @@ +# BashBox err-trap cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_err_trap_functions_do_not_inherit_the_err_trap +# functions do not inherit the ERR trap +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap 'echo err' ERR; f(){ false; echo in; }; f; echo out +### expect +in +out +### end + +### bashbox_err_trap_the_failing_call_still_fires_it +# the failing call still fires it +trap 'echo err' ERR; f(){ g; }; g(){ false; }; f; echo end +### expect +err +end +### end + +### bashbox_err_trap_set_e_passes_it_to_functions +# set -E passes it to functions +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -E; trap 'echo err $LINENO' ERR; f(){ false; }; f; echo $-; set +E; f; echo end +### expect +err 1 +err 1 +hBEc +err 1 +end +### end + +### bashbox_err_trap_a_trap_set_in_a_function_stays +# a trap set in a function stays +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ trap 'echo ferr $LINENO' ERR; false; } +f +f +false +echo end +### expect +ferr 1 +ferr 1 +ferr 3 +ferr 4 +end +### end + +### bashbox_err_trap_the_call_fires_only_a_trap_set_before_it +# the call fires only a trap set before it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ trap 'echo t' ERR; return 1; }; f; false; echo end +### expect +t +end +### end + +### bashbox_err_trap_eval_fires_the_trap_it_found +# eval fires the trap it found +trap 'echo a' ERR; eval false; eval "trap 'echo b' ERR; false"; echo end +### expect +a +a +b +b +end +### end + +### bashbox_err_trap_conditions_do_not_fire_it +# conditions do not fire it +trap 'echo err' ERR; if false; then :; elif false; then :; fi; while false; do :; done; until true; do :; done; echo end +### expect +end +### end + +### bashbox_err_trap_tested_function_calls_do_not_fire_it +# tested function calls do not fire it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap 'echo err' ERR; f(){ false; echo in; }; f || true; f && true; ! f; if f; then :; fi; echo end +### expect +in +in +in +in +end +### end + +### bashbox_err_trap_and_or_lists_fire_only_for_the_last +# and-or lists fire only for the last +trap 'echo err' ERR; false && true; false || false; echo end +### expect +err +end +### end + +### bashbox_err_trap_compound_commands_fire_only_through_their_commands +# compound commands fire only through their commands +trap 'echo err' ERR; { false; }; if true; then false; fi; for i in 1; do false; done; case x in x) false;; esac; echo end +### expect +err +err +err +err +end +### end + +### bashbox_err_trap_a_failing_subshell_fires_it_once +# a failing subshell fires it once +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap 'echo err' ERR; (false); (false; true); echo end +### expect +err +end +### end + +### bashbox_err_trap_set_e_reaches_subshells +# set -E reaches subshells +set -E; trap 'echo err' ERR; (false; true); echo end +### expect +err +end +### end + +### bashbox_err_trap_command_substitution_drops_the_err_trap +# command substitution drops the ERR trap +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap 'echo err' ERR; x=$(false; echo in); echo "[$x]"; f(){ false; }; y=$(f); echo "[$y]" +### expect +[in] +err +[] +### end + +### bashbox_err_trap_set_e_keeps_it_in_command_substitution +# set -E keeps it in command substitution +set -E; trap 'echo err' ERR; x=$(false; echo in); echo "[$x]" +### expect +[err +in] +### end + +### bashbox_err_trap_arithmetic_and_fire_it +# arithmetic and [[ ]] fire it +trap 'echo err' ERR; [[ 1 = 2 ]]; (( 0 )); echo end +### expect +err +err +end +### end + +### bashbox_err_trap_errexit_ignores_conditions +# errexit ignores conditions +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -e; if false; then :; fi; while false; do :; done; f(){ false; echo in; }; f || true; f && true; ! f; echo end +### expect +in +in +in +end +### end + +### bashbox_err_trap_set_t_passes_the_return_trap_to_functions +# set -T passes the RETURN trap to functions +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -T; echo $-; trap 'echo r' RETURN; g(){ :; }; f(){ g; }; f; echo end +### expect +hBTc +r +r +end +### end + +### bashbox_err_trap_without_t_it_stays_out_of_nested_calls +# without -T it stays out of nested calls +trap 'echo r' RETURN; g(){ :; }; f(){ g; }; f; echo end +### expect +end +### end + +### bashbox_err_trap_set_o_lists_the_options +# set -o lists the options +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -o | grep -E "errtrace|functrace"; set -E; set +o | grep errtrace +### expect +errtrace off +functrace off +set -o errtrace +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-expand.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-expand.test.sh new file mode 100644 index 000000000..858120c47 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-expand.test.sh @@ -0,0 +1,65 @@ +# BashBox expand cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_expand_past_the_last_stop_is_one_space +# past the last stop is one space +printf 'a\tb\tc\td\n' | expand -t 2,4 +### expect +a b c d +### end + +### bashbox_expand_extend +# extend +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\tb\tc\td\te\n' | expand -t 2,5,/3 +### expect +a b c d e +### end + +### bashbox_expand_increment +# increment +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\tb\tc\td\te\n' | expand -t 2,5,+3 +### expect +a b c d e +### end + +### bashbox_expand_only_extend +# only extend +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\tb\n' | expand -t /3 +### expect +a b +### end + +### bashbox_expand_only_increment +# only increment +printf 'a\tb\n' | expand -t +3 +### expect +a b +### end + +### bashbox_expand_repeated_t_adds_stops +# repeated -t adds stops +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\tb\tc\n' | expand -t 2 -t 6 +### expect +a b c +### end + +### bashbox_expand_stdin +# stdin +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '\tz\n' | expand -t 3 - +### expect + z +### end + +### bashbox_expand_slash_then_value_later +# slash then value later +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\tb\tc\n' | expand -t /,4 +### expect +a b c +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-filesystem-backends-integration.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-filesystem-backends-integration.test.sh new file mode 100644 index 000000000..bac1198f2 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-filesystem-backends-integration.test.sh @@ -0,0 +1,10 @@ +# BashBox filesystem-backends-integration cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_filesystem_backends_integration_a_file_that_may_not_be_created +# a file that may not be created +echo x > ro/new; echo $? +### expect +1 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-find-predicates.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-find-predicates.test.sh new file mode 100644 index 000000000..752565146 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-find-predicates.test.sh @@ -0,0 +1,41 @@ +# BashBox find-predicates cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_find_predicates_newer_with_h_follows_the_reference +# -newer with -H follows the reference +find -H t/fl -newer t/fl +### expect +### end + +### bashbox_find_predicates_inum_0 +# -inum 0 +find t -inum 0 +### expect +### end + +### bashbox_find_predicates_user_root +# -user root +find t -user root +### expect +### end + +### bashbox_find_predicates_nouser_and_nogroup +# -nouser and -nogroup +find t -nouser -o -nogroup +### expect +### end + +### bashbox_find_predicates_newermt_is_strictly_newer +# -newermt is strictly newer +find t -newermt '2020-01-02 03:04:05' -name f +### expect +### end + +### bashbox_find_predicates_fprint_creates_the_file_even_without_matches +# -fprint creates the file even without matches +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo old > out; find t -name nomatch -fprint out; wc -c < out +### expect +0 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-find.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-find.test.sh new file mode 100644 index 000000000..2c5b4e92d --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-find.test.sh @@ -0,0 +1,72 @@ +# BashBox find cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_find_name_is_case_sensitive +# -name is case sensitive +find . -name "main.php" +### expect +### end + +### bashbox_find_file_start_point_filtered_out +# file start point filtered out +find a.txt -type d +### expect +### end + +### bashbox_find_fractional_mtime +# fractional -mtime +find proj -type f -mtime -1.5 -mtime +0.5 +### expect +### end + +### bashbox_find_mmin_n_matches_the_minute_before +# -mmin N matches the minute before +find proj -type f -mmin 30 -o -type f -mmin 5 +### expect +### end + +### bashbox_find_perm_symbolic +# -perm symbolic +find proj ! -type l -perm u=rw,go=r -name 's*' +### expect +### end + +### bashbox_find_perm_copying_another_class +# -perm copying another class +find proj ! -type l -perm u=rw,g=u,o=u +### expect +### end + +### bashbox_find_perm_with_nothing +# -perm = with nothing +find proj ! -type l -perm = +### expect +### end + +### bashbox_find_perm_t_and_t +# -perm =t and +t +find proj -perm +t +### expect +### end + +### bashbox_find_quit_alone_prints_nothing +# -quit alone prints nothing +find proj -quit +### expect +### end + +### bashbox_find_execdir_from_the_root +# -execdir from the root +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +find / -maxdepth 0 -execdir echo {} \; +### expect +/ +### end + +### bashbox_find_printf_h_and_f_of_the_root +# -printf %h and %f of the root +find / -maxdepth 0 -printf '[%h][%f]\n' +### expect +[][/] +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-fold.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-fold.test.sh new file mode 100644 index 000000000..a9ec6dbde --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-fold.test.sh @@ -0,0 +1,69 @@ +# BashBox fold cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_fold_default_width_80 +# default width 80 +printf '%0100d\n' 0 | fold +### expect +00000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000 +### end + +### bashbox_fold_spaces_long_word +# spaces long word +printf 'abcdefghijklmnop qr\n' | fold -s -w 5 +### expect +abcde +fghij +klmno +p qr +### end + +### bashbox_fold_backspace_at_column_0 +# backspace at column 0 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '\x08abcde\n' | fold -w 3 +### expect +abc +de +### end + +### bashbox_fold_tab_wider_than_width +# tab wider than width +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '\tab\n' | fold -w 4 +### expect + +ab +### end + +### bashbox_fold_space_overflows_the_line +# space overflows the line +printf 'abcde fgh\n' | fold -s -w 5 +### expect +abcde + fgh +### end + +### bashbox_fold_line_ending_in_a_blank +# line ending in a blank +printf 'ab cd ef gh ij\n' | fold -s -w 3 +### expect +ab +cd +ef +gh +ij +### end + +### bashbox_fold_tab_after_break_with_s +# tab after break with -s +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'ab\tcdefghij\n' | fold -s -w 6 +### expect +ab + +cdefgh +ij +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-grep.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-grep.test.sh new file mode 100644 index 000000000..3a82b833a --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-grep.test.sh @@ -0,0 +1,143 @@ +# BashBox grep cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_grep_stdin +# stdin +printf 'apple\nbanana\napricot' | grep ap +### expect +apple +apricot +### end + +### bashbox_grep_h_names_stdin +# -H names stdin +echo apple | grep -Hc apple +### expect +(standard input):1 +### end + +### bashbox_grep_quiet +# quiet +grep -q cherry a.txt +### expect +### end + +### bashbox_grep_quiet_stops_at_first_match +# quiet stops at first match +grep -q apple a.txt nope +### expect +### end + +### bashbox_grep_only_matching_skips_empty_matches +# only matching skips empty matches +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo aaa | grep -o 'b*' +### expect +### end + +### bashbox_grep_only_matching_with_v_prints_nothing +# only matching with -v prints nothing +grep -ov an a.txt +### expect +### end + +### bashbox_grep_pattern_starting_with +# pattern starting with - +echo x-v | grep -e -v +### expect +x-v +### end + +### bashbox_grep_newline_separates_patterns +# newline separates patterns +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\nc\n' | grep "$(printf 'a\nc')" +### expect +a +c +### end + +### bashbox_grep_fixed_strings +# fixed strings +printf 'a.c\nabc\n' | grep -F 'a.c' +### expect +a.c +### end + +### bashbox_grep_word_match +# word match +printf 'pie\npies\n_pie\n' | grep -w pie +### expect +pie +### end + +### bashbox_grep_word_match_with_alternation +# word match with alternation +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'ab\nxa\nb\n' | grep -wE 'a|b' +### expect +b +### end + +### bashbox_grep_word_match_with_fixed_string +# word match with fixed string +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'foo.bar\nfoo.\n' | grep -wF 'foo.' +### expect +foo. +### end + +### bashbox_grep_bre_is_literal +# BRE + is literal +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a+b\nab\n' | grep 'a+b' +### expect +a+b +### end + +### bashbox_grep_bre_alternation_and_groups +# BRE alternation and groups +printf 'cat\ndog\ncow\n' | grep '^\(cat\|dog\)$' +### expect +cat +dog +### end + +### bashbox_grep_bre_back_reference +# BRE back-reference +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abab\nabba\n' | grep '\(ab\)\1' +### expect +abab +### end + +### bashbox_grep_bre_leading_star_is_literal +# BRE leading star is literal +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '*a\nb\n' | grep '*a' +### expect +*a +### end + +### bashbox_grep_ere +# ERE +printf 'aa\na\n' | grep -E '^a{2}$' +### expect +aa +### end + +### bashbox_grep_g_resets_to_bre +# -G resets to BRE +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a|b\na\n' | grep -G 'a|b' +### expect +a|b +### end + +### bashbox_grep_slash_in_pattern +# slash in pattern +echo 'a/b' | grep 'a/b' +### expect +a/b +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-head-tail.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-head-tail.test.sh new file mode 100644 index 000000000..5a0f4e20a --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-head-tail.test.sh @@ -0,0 +1,35 @@ +# BashBox head-tail cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_head_tail_head_defaults_to_10_lines +# head defaults to 10 lines +seq 12 | head +### expect +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +### end + +### bashbox_head_tail_tail_defaults_to_10_lines +# tail defaults to 10 lines +seq 12 | tail +### expect +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-builtins.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-builtins.test.sh new file mode 100644 index 000000000..e56258158 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-builtins.test.sh @@ -0,0 +1,533 @@ +# BashBox interpreter-builtins cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_interpreter_builtins_for_without_in_walks_the_positional_parameters +# for without in walks the positional parameters +set -- a b c; for x; do echo $x; done +### expect +a +b +c +### end + +### bashbox_interpreter_builtins_c_style_for_with_continue_and_break +# c-style for with continue and break +for ((i=0; i<10; i++)); do test $i = 1 && continue; test $i = 3 && break; echo $i; done +### expect +0 +2 +### end + +### bashbox_interpreter_builtins_c_style_for_with_no_clauses_loops_until_break +# c-style for with no clauses loops until break +i=0; for ((;;)); do i=$((i+1)); test $i -gt 2 && break; echo $i; done +### expect +1 +2 +### end + +### bashbox_interpreter_builtins_loop_status_is_the_last_body_status +# loop status is the last body status +for ((i=0; i<2; i++)); do false; done; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_while_with_continue_and_break +# while with continue and break +i=0; while test $i -lt 5; do i=$((i+1)); test $i = 2 && continue; test $i = 4 && break; echo $i; done +### expect +1 +3 +### end + +### bashbox_interpreter_builtins_while_break_2_from_a_nested_while +# while break 2 from a nested while +for a in x y; do while true; do while true; do break 2; done; done; echo $a; done +### expect +x +y +### end + +### bashbox_interpreter_builtins_while_continue_3_resumes_the_outer_for +# while continue 3 resumes the outer for +for a in x y; do while true; do while true; do continue 3; done; done; echo no; done; echo done +### expect +done +### end + +### bashbox_interpreter_builtins_while_that_never_runs_exits_0 +# while that never runs exits 0 +while false; do :; done; echo $? +### expect +0 +### end + +### bashbox_interpreter_builtins_until_counts_up +# until counts up +i=0; until test $i -ge 3; do echo $i; i=$((i+1)); done +### expect +0 +1 +2 +### end + +### bashbox_interpreter_builtins_until_with_continue_and_break +# until with continue and break +i=0; until false; do i=$((i+1)); test $i = 2 && continue; test $i = 4 && break; echo $i; done +### expect +1 +3 +### end + +### bashbox_interpreter_builtins_until_status_is_the_last_body_status +# until status is the last body status +i=0; until test $i = 2; do i=$((i+1)); false; done; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_runs_the_next_body_without_testing_it +# ;& runs the next body without testing it +case a in a) echo 1;& b) echo 2;; c) echo 3;; esac +### expect +1 +2 +### end + +### bashbox_interpreter_builtins_goes_on_testing_the_next_patterns +# ;;& goes on testing the next patterns +case ab in a*) echo 1;;& *b) echo 2;;& c) echo 3;; esac +### expect +1 +2 +### end + +### bashbox_interpreter_builtins_no_match_exits_0 +# no match exits 0 +case x in y) echo no;; esac; echo $? +### expect +0 +### end + +### bashbox_interpreter_builtins_status_of_the_matched_body +# status of the matched body +case x in x) false;; esac; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_quoted_backslash +# quoted backslash +case 'a\' in 'a\') echo bs;; esac +### expect +bs +### end + +### bashbox_interpreter_builtins_unclosed_bracket_is_literal +# unclosed bracket is literal +case ab in a[b) echo open;; *) echo other;; esac +### expect +other +### end + +### bashbox_interpreter_builtins_exit_ends_only_the_subshell +# exit ends only the subshell +(exit 3); echo $? +### expect +3 +### end + +### bashbox_interpreter_builtins_return_ends_only_the_subshell +# return ends only the subshell +f(){ (return 4); echo $?; }; f +### expect +4 +### end + +### bashbox_interpreter_builtins_errexit_ends_only_the_subshell +# errexit ends only the subshell +(set -e; false; echo no); echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_keeps_earlier_output_in_place +# keeps earlier output in place +echo pre; x=$(echo b); echo "[$x]" +### expect +pre +[b] +### end + +### bashbox_interpreter_builtins_exit_status_reaches +# exit status reaches $? +x=$(exit 4); echo $? +### expect +4 +### end + +### bashbox_interpreter_builtins_state_changes_stay_inside +# state changes stay inside +x=1; y=$(x=2; f(){ :; }; echo $x); echo $x $y; type f >/dev/null 2>&1; echo $? +### expect +1 2 +1 +### end + +### bashbox_interpreter_builtins_does_not_fire_the_exit_trap +# does not fire the EXIT trap +trap 'echo bye' EXIT; x=$(echo a); echo $x +### expect +a +bye +### end + +### bashbox_interpreter_builtins_an_expansion_error_ends_only_the_substitution +# an expansion error ends only the substitution +x=$(echo ${zz:?boom}); echo "after $?" +### expect +after 1 +### end + +### bashbox_interpreter_builtins_fires_after_the_body_of_the_function_that_set_it +# fires after the body of the function that set it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ trap 'echo ret' RETURN; echo in; }; f; echo after +### expect +in +ret +after +### end + +### bashbox_interpreter_builtins_is_not_inherited_by_functions +# is not inherited by functions +trap 'echo ret' RETURN; f(){ echo f; }; f; echo end +### expect +f +end +### end + +### bashbox_interpreter_builtins_stays_set_but_other_functions_do_not_see_it +# stays set but other functions do not see it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ trap 'echo ret' RETURN; }; g(){ echo g; }; f; echo top; g; h(){ g; }; h +### expect +ret +top +g +g +### end + +### bashbox_interpreter_builtins_sees_the_function_locals +# sees the function locals +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ local v=loc; trap 'echo $v' RETURN; }; f +### expect +loc +### end + +### bashbox_interpreter_builtins_input_from_a_missing_file +# input from a missing file +cat < missing.txt; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_creates_the_file +# <> creates the file +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +cat <> rw.txt; echo $?; test -f rw.txt && echo created +### expect +0 +created +### end + +### bashbox_interpreter_builtins_2_1_before_dev_null_keeps_stderr_on_the_pipe +# 2>&1 before >/dev/null keeps stderr on the pipe +{ echo out; echo err >&2; } 2>&1 >/dev/null | cat +### expect +err +### end + +### bashbox_interpreter_builtins_closing_stderr +# closing stderr +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +ls /nope 2>&-; echo y +### expect +y +### end + +### bashbox_interpreter_builtins_file_sends_both_streams_to_the_file +# >&file sends both streams to the file +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +{ echo z; echo e >&2; } >& both.txt; cat both.txt +### expect +z +e +### end + +### bashbox_interpreter_builtins_and_write_and_append_both_streams +# &> and &>> write and append both streams +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +{ echo a; echo b >&2; } &> all.txt; { echo c; } &>> all.txt; cat all.txt +### expect +a +b +c +### end + +### bashbox_interpreter_builtins_dev_stderr_is_fd_2_as_of_that_redirection +# /dev/stderr is fd 2 as of that redirection +echo x > /dev/stderr 2>/dev/null; echo y +### expect +y +### end + +### bashbox_interpreter_builtins_a_missing_directory_fails +# a missing directory fails > +echo a > /no/such/dir/f; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_a_missing_directory_fails_2 +# a missing directory fails >& +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo z >& /no/such/dir/f; echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_quoted_heredoc_stays_literal +# quoted heredoc stays literal +cat <<'EOF' +$HOME x +EOF +### expect +$HOME x +### end + +### bashbox_interpreter_builtins_strips_leading_tabs_and_expands +# <<- strips leading tabs and expands +cat <<-EOF + tab $((1+1)) + EOF +### expect +tab 2 +### end + +### bashbox_interpreter_builtins_here_string +# here-string +cat <<< "here $((2+3))" +### expect +here 5 +### end + +### bashbox_interpreter_builtins_an_empty_array +# an empty array +a=(); echo ${#a[@]}; a=(1 2 3); a=(); echo ${#a[@]} +### expect +0 +0 +### end + +### bashbox_interpreter_builtins_to_a_readonly_variable_fails +# to a readonly variable fails +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly r=1 +r=2 +echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_xtrace_of_a_prefix_assignment +# xtrace of a prefix assignment +set -x; X=1 echo hi +### expect +hi +### end + +### bashbox_interpreter_builtins_and_short_circuit +# && and || short-circuit +x=0; echo $((0 && (x=5))) $x $((1 || (x=6))) $x $((1 && 2)) $((0 || 0)) $((0 || 3)) +### expect +0 0 1 0 1 0 1 +### end + +### bashbox_interpreter_builtins_unary_operators +# unary operators +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo $((-(2+3))) $((+4)) $((!0)) $((!5)) $((~0)) $((++5)) $((--5)) +### expect +-5 4 1 0 -1 5 5 +### end + +### bashbox_interpreter_builtins_increment_and_decrement +# increment and decrement +x=5; echo $((x++)) $x $((x--)) $x $((++x)) $((--x)); echo $((y++)) $y +### expect +5 6 6 5 6 5 +0 1 +### end + +### bashbox_interpreter_builtins_ternary +# ternary +echo $((1?2:3)) $((0?2:3)) +### expect +2 3 +### end + +### bashbox_interpreter_builtins_variables_holding_expressions +# variables holding expressions +x=1+2; echo $((x*3)) $(($x*3)) +### expect +9 7 +### end + +### bashbox_interpreter_builtins_positional_parameters +# positional parameters +set -- 5; echo $(($1+1)); (( $1 == 5 )) && echo five +### expect +6 +five +### end + +### bashbox_interpreter_builtins_expansions_and_quotes_inside +# expansions and quotes inside +a=(1 2 3); echo $(("1"+1)) $(( $(echo 2) * 3 )) $(( ${#a[@]} + 1 )) +### expect +2 6 4 +### end + +### bashbox_interpreter_builtins_associative_array_elements +# associative array elements +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -A m; m[foo]=5; echo $((m[foo]*2)); (( m[bar]=3 )); echo ${m[bar]} +### expect +10 +3 +### end + +### bashbox_interpreter_builtins_command_status +# command status +((0)); echo $?; ((2)); echo $? +### expect +1 +0 +### end + +### bashbox_interpreter_builtins_c_style_for_header_with_a_substitution +# c-style for header with a substitution +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +for ((i=$(echo 1); i<3; i++)); do echo $i; done +### expect +1 +2 +### end + +### bashbox_interpreter_builtins_case +# /= +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=5; ((x/=0)); echo $? $x +### expect +1 5 +### end + +### bashbox_interpreter_builtins_case_2 +# %= +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=5; ((x%=0)); echo $? $x +### expect +1 5 +### end + +### bashbox_interpreter_builtins_case_3 +# / +((5/0)); echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_case_4 +# % +((5%0)); echo $? +### expect +1 +### end + +### bashbox_interpreter_builtins_string_comparisons +# string comparisons +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +[[ abc != a* ]]; echo $?; [[ abc != x* ]]; echo $?; [[ a < b ]]; echo $?; [[ b > a ]]; echo $?; [[ b < a ]]; echo $? +### expect +1 +0 +0 +0 +1 +### end + +### bashbox_interpreter_builtins_integer_comparisons +# integer comparisons +[[ 3 -eq 3 && 3 -ne 4 && 2 -lt 3 && 3 -le 3 && 4 -gt 3 && 4 -ge 4 ]]; echo $?; [[ 3 -eq 4 ]]; echo $? +### expect +0 +1 +### end + +### bashbox_interpreter_builtins_regex_match +# regex match +[[ abc123 =~ [0-9]+ ]]; echo $?; [[ abc =~ ^b ]]; echo $? +### expect +0 +1 +### end + +### bashbox_interpreter_builtins_regex_fills_bash_rematch +# regex fills BASH_REMATCH +re="(b)(c)"; [[ abc =~ $re ]]; echo $? ${BASH_REMATCH[0]} ${BASH_REMATCH[2]}; [[ a/b =~ a/b ]]; echo $? +### expect +0 bc c +0 +### end + +### bashbox_interpreter_builtins_empty_and_non_empty_strings +# empty and non-empty strings +[[ -z "" && -n x ]]; echo $?; [[ -z x ]]; echo $?; [[ x ]]; echo $?; [[ "" ]]; echo $? +### expect +0 +1 +0 +1 +### end + +### bashbox_interpreter_builtins_variable_is_set +# variable is set +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +v=1; a=(1 2); [[ -v v ]]; echo $?; [[ -v a ]]; echo $?; [[ -v nope ]]; echo $? +### expect +0 +0 +1 +### end + +### bashbox_interpreter_builtins_and_match_newlines +# * and ? match newlines +x=$(printf "a\nb"); [[ $x == a* ]]; echo $?; case $x in a?b) echo nl;; esac +### expect +0 +nl +### end + +### bashbox_interpreter_builtins_unset_in_its_own_function_keeps_a_local_hiding_the_global +# unset in its own function keeps a local hiding the global +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ local x=1; unset x; echo "[${x-unset}]"; x=2; echo $x; }; x=g; f; echo $x +### expect +[unset] +2 +g +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-core.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-core.test.sh new file mode 100644 index 000000000..cfb628064 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-interpreter-core.test.sh @@ -0,0 +1,1053 @@ +# BashBox interpreter-core cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_interpreter_core_command_substitution_captures_only_its_own_output +# command substitution captures only its own output +echo a; x=$(echo b); echo "[$x]" +### expect +a +[b] +### end + +### bashbox_interpreter_core_exit_inside_command_substitution_ends_only_the_subshell +# exit inside command substitution ends only the subshell +x=$(echo in; exit 3); echo "$? [$x]" +### expect +3 [in] +### end + +### bashbox_interpreter_core_assignment_only_command_reports_the_substitution_status +# assignment-only command reports the substitution status +x=$(false); echo $? +### expect +1 +### end + +### bashbox_interpreter_core_exit_trap_waits_for_the_whole_script +# EXIT trap waits for the whole script +trap "echo bye" EXIT; eval "echo hi"; x=$(echo in); echo "after $x" +### expect +hi +after in +bye +### end + +### bashbox_interpreter_core_empty_exit_trap_is_ignored +# empty EXIT trap is ignored +trap "" EXIT; echo x +### expect +x +### end + +### bashbox_interpreter_core_skipped_still_reaches +# skipped && still reaches || +false && echo a || echo b +### expect +b +### end + +### bashbox_interpreter_core_skips_on_success +# || skips on success +true || echo no; echo $? +### expect +0 +### end + +### bashbox_interpreter_core_err_trap_fires_for_a_failing_command +# ERR trap fires for a failing command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap "echo caught \$?" ERR; false; echo next $? +### expect +caught 1 +next 1 +### end + +### bashbox_interpreter_core_err_trap_skips_non_final_members_of_an_and_or_list +# ERR trap skips non-final members of an and-or list +trap "echo caught" ERR; false && true; false || true; echo done +### expect +done +### end + +### bashbox_interpreter_core_set_e_ignores_a_failure_before +# set -e ignores a failure before && +set -e; false && true; echo yes +### expect +yes +### end + +### bashbox_interpreter_core_set_e_ignores_a_negated_pipeline +# set -e ignores a negated pipeline +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -e; ! true; echo yes +### expect +yes +### end + +### bashbox_interpreter_core_set_o_errexit_then_set_e +# set -o errexit then set +e +set -o errexit; set +e; false; echo yes +### expect +yes +### end + +### bashbox_interpreter_core_pipeline_status_is_the_last_command +# pipeline status is the last command +false | true; echo $? +### expect +0 +### end + +### bashbox_interpreter_core_negated_pipeline +# negated pipeline +! false; echo $?; ! true; echo $? +### expect +0 +1 +### end + +### bashbox_interpreter_core_pipefail_reports_the_rightmost_failure +# pipefail reports the rightmost failure +set -o pipefail; false | true; echo $?; set +o pipefail; false | true; echo $? +### expect +1 +0 +### end + +### bashbox_interpreter_core_pipes_stderr_too +# |& pipes stderr too +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +{ echo out; echo err >&2; } |& cat +### expect +out +err +### end + +### bashbox_interpreter_core_stderr_of_a_piped_command_is_not_piped +# stderr of a piped command is not piped +{ echo out; echo err >&2; } | cat +### expect +out +### end + +### bashbox_interpreter_core_compound_command_output_is_redirected +# compound command output is redirected +{ echo a; echo b >&2; } > out 2>&1; cat out +### expect +a +b +### end + +### bashbox_interpreter_core_loop_reads_from_a_redirected_file +# loop reads from a redirected file +printf "1\n2\n" > in; while read l; do echo $l; done < in +### expect +1 +2 +### end + +### bashbox_interpreter_core_failed_compound_redirection_skips_the_command +# failed compound redirection skips the command +while read l; do echo "<$l>"; done < nofile; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_every_compound_command_kind_runs +# every compound command kind runs +if true; then echo t; fi | cat; case a in a) echo c;; esac; (echo sub); ((1)) && [[ a ]] && echo arith; until true; do :; done; for ((i=0; i<1; i++)); do echo $i; done +### expect +t +c +sub +arith +0 +### end + +### bashbox_interpreter_core_break_and_continue_with_levels +# break and continue with levels +for i in 1 2 3; do for j in a b; do test $j = b && continue 2; test $i = 3 && break 2; echo $i$j; done; done; until false; do break; done; echo end +### expect +1a +2a +end +### end + +### bashbox_interpreter_core_break_and_continue_outside_a_loop +# break and continue outside a loop +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +break; continue 2; echo $? +### expect +0 +### end + +### bashbox_interpreter_core_break_inside_a_function_cannot_leave_the_caller_loop +# break inside a function cannot leave the caller loop +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() { break; }; for i in 1; do f; echo no; done +### expect +no +### end + +### bashbox_interpreter_core_command_not_found +# command not found +nope; echo $? +### expect +127 +### end + +### bashbox_interpreter_core_command_name_is_field_split +# command name is field split +CMD="echo a b"; $CMD c +### expect +a b c +### end + +### bashbox_interpreter_core_empty_expansion_leaves_only_the_assignment +# empty expansion leaves only the assignment +e=; x=1 $e; echo $x +### expect +1 +### end + +### bashbox_interpreter_core_prefix_assignment_reaches_a_command_env_only +# prefix assignment reaches a command env only +FOO=bar printenv FOO; echo "[$FOO]" +### expect +bar +[] +### end + +### bashbox_interpreter_core_prefix_assignment_is_temporary_for_functions +# prefix assignment is temporary for functions +f() { echo "x=$x"; }; x=1 f; echo "[$x]" +### expect +x=1 +[] +### end + +### bashbox_interpreter_core_prefix_assignment_is_temporary_for_builtins +# prefix assignment is temporary for builtins +y=0; y=5 eval "echo \$y"; echo $y +### expect +5 +0 +### end + +### bashbox_interpreter_core_repeated_prefix_assignment_restores_the_original +# repeated prefix assignment restores the original +x=0; x=1 x=2 printenv x; echo $x +### expect +2 +0 +### end + +### bashbox_interpreter_core_readonly_prefix_assignment_is_reported_the_command_still_run +# readonly prefix assignment is reported, the command still runs +readonly R=1; R=2 echo "[$R]"; echo "s=$?" +### expect +[1] +s=0 +### end + +### bashbox_interpreter_core_xtrace_prints_assignments_and_commands +# xtrace prints assignments and commands +set -x; x=1 printenv x; y=2 +### expect +1 +### end + +### bashbox_interpreter_core_bad_substitution_fails_only_its_command +# bad substitution fails only its command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo ${x!} +echo after $? +### expect +after 1 +### end + +### bashbox_interpreter_core_expansion_error_abandons_the_rest_of_its_line +# expansion error abandons the rest of its line +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() { echo ${x!}; echo in; } +f; echo same +echo next +### expect +next +### end + +### bashbox_interpreter_core_cannot_assign_fails_only_its_command +# cannot assign fails only its command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo ${1:=x} +echo after $? +### expect +after 1 +### end + +### bashbox_interpreter_core_return_1_wraps_to_255 +# return -1 wraps to 255 +f() { return -1; }; f; echo $? +### expect +255 +### end + +### bashbox_interpreter_core_return_outside_a_function +# return outside a function +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +return; echo $? +### expect +2 +### end + +### bashbox_interpreter_core_export_tracks_later_assignments +# export tracks later assignments +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export X=1; X=2; printenv X; export Y; Y=3; printenv Y; export -n Z=4; echo $Z +### expect +2 +3 +4 +### end + +### bashbox_interpreter_core_export_of_a_readonly_variable +# export of a readonly variable +readonly R=1; export R=2; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_export_lists_variables +# export lists variables +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +export B=2 A=1; export | grep "[AB]=" +### expect +declare -x A="1" +declare -x B="2" +### end + +### bashbox_interpreter_core_unset_f_and_v +# unset -f and -v +f() { echo fn; }; unset -f f; f; a=1; unset -v a; echo "[$a]" +### expect +[] +### end + +### bashbox_interpreter_core_unset_an_array_element +# unset an array element +a=(1 2 3); unset "a[1]"; echo ${a[@]} +### expect +1 3 +### end + +### bashbox_interpreter_core_unset_a_whole_array +# unset a whole array +a=(1 2); unset a; echo "[${a[@]}]" +### expect +[] +### end + +### bashbox_interpreter_core_unset_a_readonly_variable +# unset a readonly variable +readonly r=1; unset r; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_local_outside_a_function +# local outside a function +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +local x=1; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_local_variables_vanish_after_the_function +# local variables vanish after the function +f() { local a=1 b; b=2; echo $a$b; }; f; echo "[$a$b]" +### expect +12 +[] +### end + +### bashbox_interpreter_core_local_of_a_readonly_variable +# local of a readonly variable +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly r=1; f() { local r=2; }; f; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_set_lists_variables_quoting_when_needed +# set lists variables, quoting when needed +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=1; b="x y"; c=""; d="it's"; set | grep "^[abcd]=" +### expect +a=1 +b='x y' +c= +d='it'\''s' +### end + +### bashbox_interpreter_core_set_positional_parameters +# set positional parameters +set -- x y; echo $# $1; set a b; echo $2 +### expect +2 x +b +### end + +### bashbox_interpreter_core_set_c_and_c +# set -C and +C +set -C; echo a > f; echo b > f; echo $?; set +C; echo c > f; cat f +### expect +1 +c +### end + +### bashbox_interpreter_core_set_f_disables_globbing +# set -f disables globbing +touch a.txt; set -f; echo *.txt; set +f; echo *.txt +### expect +*.txt +a.txt +### end + +### bashbox_interpreter_core_set_v_has_no_effect_on_a_one_line_script +# set -v has no effect on a one-line script +set -v; echo hi +### expect +hi +### end + +### bashbox_interpreter_core_set_u_and_u +# set -u and +u +set -u; set +u; echo "[$nope]" +### expect +[] +### end + +### bashbox_interpreter_core_set_x_stops_tracing +# set +x stops tracing +set -x; set +x; echo hi +### expect +hi +### end + +### bashbox_interpreter_core_shopt_succeeds +# shopt succeeds +shopt -s nullglob; echo $? +### expect +0 +### end + +### bashbox_interpreter_core_source_without_a_file +# source without a file +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +source; echo $? +### expect +2 +### end + +### bashbox_interpreter_core_source_a_missing_file +# source a missing file +source nope.sh; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_source_arguments_become_positional_parameters +# source arguments become positional parameters +echo "echo sourced \$1 \$#" > s.sh; set -- p q; source s.sh arg; . ./s.sh; echo $1 +### expect +sourced arg 1 +sourced p 2 +p +### end + +### bashbox_interpreter_core_source_without_arguments_can_set_positional_parameters +# source without arguments can set positional parameters +echo "set -- z" > s.sh; source s.sh; echo $1 +### expect +z +### end + +### bashbox_interpreter_core_return_ends_a_sourced_file +# return ends a sourced file +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo "return 4; echo no" > s.sh; source s.sh; echo $? +### expect +4 +### end + +### bashbox_interpreter_core_return_in_a_file_sourced_by_a_function +# return in a file sourced by a function +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo "x=1; return 5; x=2" > s; f() { source ./s; echo "s=$? x=$x"; }; f +### expect +s=5 x=1 +### end + +### bashbox_interpreter_core_eval_runs_in_the_current_shell +# eval runs in the current shell +eval "a=1;" "echo \$a"; eval; echo $? +### expect +1 +0 +### end + +### bashbox_interpreter_core_eval_output_follows_its_redirection +# eval output follows its redirection +echo a; eval "echo b" > f; cat f +### expect +a +b +### end + +### bashbox_interpreter_core_declare_without_a_value_keeps_the_variable +# declare without a value keeps the variable +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; declare x; echo $x; declare -p x nope; echo $? +### expect +1 +declare -- x="1" +1 +### end + +### bashbox_interpreter_core_declare_p_readonly_and_arrays +# declare -p readonly and arrays +declare -r y=2; declare -p y; a=(1 "b c"); declare -p a +### expect +declare -r y="2" +declare -a a=([0]="1" [1]="b c") +### end + +### bashbox_interpreter_core_declare_in_a_function_is_local_unless_g +# declare in a function is local unless -g +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() { declare x=1; declare -g g=2; }; f; echo "[$x][$g]" +### expect +[][2] +### end + +### bashbox_interpreter_core_declare_a +# declare -a +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -a arr; arr[0]=x; echo ${arr[0]}; declare -a b=v; echo ${b[0]} +### expect +x +v +### end + +### bashbox_interpreter_core_declare_of_a_readonly_variable +# declare of a readonly variable +readonly RO=1; declare RO=2; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_declare_x +# declare -x +declare -x E=1; printenv E +### expect +1 +### end + +### bashbox_interpreter_core_declare_alone_lists_variables +# declare alone lists variables +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +q=1; declare | grep "^q=" +### expect +q=1 +### end + +### bashbox_interpreter_core_let_without_arguments +# let without arguments +let; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_let_status_follows_the_last_value +# let status follows the last value +let x=0; echo $?; let y=2 z=3; echo $y$z $? +### expect +1 +23 0 +### end + +### bashbox_interpreter_core_shift +# shift +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- a b c; shift; echo $*; shift 2; echo $# $?; shift; echo $? +### expect +b c +0 0 +1 +### end + +### bashbox_interpreter_core_getopts_walks_grouped_options_and_arguments +# getopts walks grouped options and arguments +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- -ac -bval -- -z rest1; while getopts "ab:c" o; do echo "$o ${OPTARG-unset} $OPTIND"; done; shift $((OPTIND-1)); echo "rest: $*" +### expect +a unset 1 +c unset 2 +b val 3 +rest: -z rest1 +### end + +### bashbox_interpreter_core_getopts_silent_mode +# getopts silent mode +set -- -z -b; while getopts ":ab:" o; do echo "$o ${OPTARG-unset}"; done +### expect +? z +: b +### end + +### bashbox_interpreter_core_getopts_reports_errors +# getopts reports errors +set -- -z -b; while getopts "ab:" o; do echo "$o ${OPTARG-unset}"; done +### expect +? unset +? unset +### end + +### bashbox_interpreter_core_getopts_with_explicit_arguments +# getopts with explicit arguments +getopts a o -a -b; echo "$o $?"; getopts a o -a -b; echo "$o $? ${OPTARG-u}"; getopts a o -a -b; echo "$o $?" +### expect +a 0 +? 0 u +? 1 +### end + +### bashbox_interpreter_core_getopts_restarts_when_optind_is_reset +# getopts restarts when OPTIND is reset +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +getopts ab o -ab; echo $o; OPTIND=1; getopts xy o -x; echo $o +### expect +a +x +### end + +### bashbox_interpreter_core_getopts_stops_at_a_non_option +# getopts stops at a non-option +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- a -b; getopts b o; echo "$? $o $OPTIND" +### expect +1 ? 1 +### end + +### bashbox_interpreter_core_getopts_option_argument_in_the_next_word +# getopts option argument in the next word +getopts "a:" o -a val; echo "$o $OPTARG $OPTIND" +### expect +a val 3 +### end + +### bashbox_interpreter_core_getopts_usage +# getopts usage +getopts; echo $? +### expect +2 +### end + +### bashbox_interpreter_core_type_t +# type -t +f(){ :; }; type -t f cd ls echo nope; echo $? +### expect +function +builtin +file +builtin +1 +### end + +### bashbox_interpreter_core_type_describes_each_name +# type describes each name +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +type nope cd ls; echo $? +### expect +cd is a shell builtin +ls is /usr/bin/ls +1 +### end + +### bashbox_interpreter_core_command_v +# command -v +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f(){ :; }; command -v cd ls f nope; echo $?; command -v nope; echo $? +### expect +cd +/usr/bin/ls +f +0 +1 +### end + +### bashbox_interpreter_core_command_skips_functions +# command skips functions +f(){ :; }; command f; echo $?; command; echo $?; echo() { :; }; command echo hi +### expect +127 +0 +hi +### end + +### bashbox_interpreter_core_command_runs_builtins +# command runs builtins +command cd /tmp; pwd +### expect +/tmp +### end + +### bashbox_interpreter_core_builtin +# builtin +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +builtin cd /tmp && pwd; builtin echo hi; builtin cat; echo $?; builtin; echo $? +### expect +/tmp +hi +1 +0 +### end + +### bashbox_interpreter_core_exec_runs_a_command_and_ends_the_script +# exec runs a command and ends the script +exec echo done; echo no +### expect +done +### end + +### bashbox_interpreter_core_exec_without_a_command +# exec without a command +exec; echo still +### expect +still +### end + +### bashbox_interpreter_core_alias_define_list_and_query +# alias define, list and query +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +alias a=b c="it's"; alias; alias a; alias zz; echo $? +### expect +alias a='b' +alias c='it'\''s' +alias a='b' +1 +### end + +### bashbox_interpreter_core_unalias +# unalias +alias a=b; unalias a zz; echo $?; alias x=y; unalias -a; alias +### expect +1 +### end + +### bashbox_interpreter_core_trap_listing_order_and_quoting +# trap listing order and quoting +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap "echo b" ERR; trap "echo a" EXIT; trap "" INT; trap "it's" SIGTERM; trap +### expect +trap -- 'echo a' EXIT +trap -- '' SIGINT +trap -- 'it'\''s' SIGTERM +trap -- 'echo b' ERR +a +### end + +### bashbox_interpreter_core_trap_with_a_lone_signal_resets_it +# trap with a lone signal resets it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap "echo x" 0; trap; trap EXIT; trap; echo done +### expect +trap -- 'echo x' EXIT +done +### end + +### bashbox_interpreter_core_err_trap_keeps +# ERR trap keeps $? +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +trap "true" ERR; false; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_pushd_and_popd +# pushd and popd +cd /tmp; mkdir -p /tmp/a /tmp/b; pushd /tmp/a; pushd /tmp/b; pushd; popd; popd; popd; echo $? +### expect +/tmp/a /tmp +/tmp/b /tmp/a /tmp +/tmp/a /tmp/b /tmp +/tmp/b /tmp +/tmp +1 +### end + +### bashbox_interpreter_core_pushd_without_a_stack +# pushd without a stack +pushd; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_pushd_to_a_missing_directory +# pushd to a missing directory +pushd /nope; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_pushd_abbreviates_home +# pushd abbreviates HOME +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +cd /tmp; pushd ~ +### expect +~ /tmp +### end + +### bashbox_interpreter_core_hash +# hash +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +hash; hash -r; : a b; echo $? +### expect +hash: hash table empty +0 +### end + +### bashbox_interpreter_core_reply_is_not_trimmed +# REPLY is not trimmed +echo " a b " | { read; echo "[$REPLY]"; } +### expect +[ a b ] +### end + +### bashbox_interpreter_core_non_whitespace_ifs_keeps_the_rest_intact +# non-whitespace IFS keeps the rest intact +echo "a:b:c:d" | { IFS=: read x y; echo "[$x][$y]"; } +### expect +[a][b:c:d] +### end + +### bashbox_interpreter_core_adjacent_separators_make_empty_fields +# adjacent separators make empty fields +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo "a::b" | { IFS=: read -a x; echo "${#x[@]} [${x[1]}]"; } +### expect +3 [] +### end + +### bashbox_interpreter_core_unterminated_line_assigns_but_fails +# unterminated line assigns but fails +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf "a b" | { read x; echo "$? [$x]"; } +### expect +1 [a b] +### end + +### bashbox_interpreter_core_escaped_separator_stays_in_the_field +# escaped separator stays in the field +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo "a\\ b c" | { read x y; echo "[$x][$y]"; } +### expect +[a b][c] +### end + +### bashbox_interpreter_core_empty_ifs_disables_splitting +# empty IFS disables splitting +printf "x y" | { IFS= read -r v; echo "[$v]"; } +### expect +[x y] +### end + +### bashbox_interpreter_core_nul_delimited_records +# NUL delimited records +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf "a\0b\0" | while read -r -d "" v; do echo "[$v]"; done +### expect +[a] +[b] +### end + +### bashbox_interpreter_core_mapfile_on_nul_delimiters +# mapfile on NUL delimiters +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf "a\0b\0" | { mapfile -d "" arr; echo ${#arr[@]}; } +### expect +2 +### end + +### bashbox_interpreter_core_readarray_t_into_mapfile +# readarray -t into MAPFILE +printf "a\nb" | { readarray -t; echo "${MAPFILE[1]}"; } +### expect +b +### end + +### bashbox_interpreter_core_read_from_a_pipe_into_eval +# read from a pipe into eval +echo hi | eval "read x; echo \$x" +### expect +hi +### end + +### bashbox_interpreter_core_default +# default +time echo hi +### expect +hi +### end + +### bashbox_interpreter_core_posix +# posix +time -p true +### expect +### end + +### bashbox_interpreter_core_an_invalid_regex_fails_with_status_2 +# an invalid regex fails [[ with status 2 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +re='('; [[ a =~ $re ]]; echo $?; re='[[:foo:]]'; [[ a =~ $re ]]; echo $?; [[ abc =~ b(c) ]]; echo $? ${BASH_REMATCH[@]} +### expect +2 +2 +0 bc c +### end + +### bashbox_interpreter_core_evaluates_integer_operands_without_expanding_them_again +# [[ ]] evaluates integer operands without expanding them again +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x='$(echo hi >&2; echo 1)'; [[ $x -eq 1 ]]; echo $?; x='1+1'; [[ $x -eq 2 ]]; echo $?; [[ 08 -eq 1 ]]; echo $? +### expect +1 +0 +1 +### end + +### bashbox_interpreter_core_assignment_subscripts_are_expanded_and_arithmetic_for_indexe +# assignment subscripts are expanded, and arithmetic for indexed arrays +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +i=3; a[$i]=x; a[i+1]=y; a[-1]=z; b=([i+1]=p [6]=q); read 'c[1+1]' <<< r; declare -p a b c +### expect +declare -a a=([3]="x" [4]="z") +declare -a b=([4]="p" [6]="q") +declare -a c=([2]="r") +### end + +### bashbox_interpreter_core_an_associative_array_s_subscript_is_its_key +# an associative array's subscript is its key +declare -A m; k='a b'; m[$k]=1; m[1+1]=2; echo "${m[a b]} ${m[1+1]}" +### expect +1 2 +### end + +### bashbox_interpreter_core_a_negative_subscript_counts_back_from_the_end +# a negative subscript counts back from the end +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1 2 3); a[-1]+=x; declare -p a; a[-5]=q; echo same +echo next $? +### expect +declare -a a=([0]="1" [1]="2" [2]="3x") +next 1 +### end + +### bashbox_interpreter_core_unset_takes_options_first +# unset takes options first +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +unset -v x -n y; echo $?; unset -z; echo $?; unset -fn; echo $?; unset -n; echo $?; unset 'a b'; echo $? +### expect +1 +2 +0 +0 +0 +### end + +### bashbox_interpreter_core_unset_of_an_element_and_of_a_readonly_variable +# unset of an element and of a readonly variable +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1 2 3); unset 'a[1]'; declare -p a; readonly r; unset -n r; echo $?; readonly -a ra=(1); unset 'ra[0]'; echo $? +### expect +declare -a a=([0]="1" [2]="3") +1 +1 +### end + +### bashbox_interpreter_core_set_n_reads_the_rest_without_running_it +# set -n reads the rest without running it +echo a; set -n; echo b +### expect +a +### end + +### bashbox_interpreter_core_set_o_noexec_too +# set -o noexec too +set -o noexec; echo hi +### expect +### end + +### bashbox_interpreter_core_set_k_takes_assignments_from_anywhere_in_a_command +# set -k takes assignments from anywhere in a command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() { echo "$x"; }; set -k; echo a=b c; f x=5; echo $-; set +k; echo a=b +### expect +c +5 +hkBc +a=b +### end + +### bashbox_interpreter_core_a_subscript_may_quote_or_escape_a +# a subscript may quote or escape a ] +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +declare -A a b c; a["x]"]=1; b[\]]=2; c['y z']=3; declare -p a b c +### expect +declare -A a=(["x]"]="1" ) +declare -A b=(["]"]="2" ) +declare -A c=(["y z"]="3" ) +### end + +### bashbox_interpreter_core_unset_stops_taking_options_at +# unset stops taking options at -- +x=1; unset -- x; echo $? ${x-unset} +### expect +0 unset +### end + +### bashbox_interpreter_core_redirections_report_why_a_file_can_t_be_opened +# redirections report why a file can't be opened +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +true <> /tmp; echo $?; touch f; echo hi > f/x; echo $?; cat < f/x; echo $?; ln -s loop loop; echo hi > loop; echo $? +### expect +1 +1 +1 +1 +### end + +### bashbox_interpreter_core_reading_a_directory_fails +# reading a directory fails +cat < /tmp; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_source_names_a_directory_it_can_t_read +# source names a directory it can't read +source /tmp; echo $? +### expect +1 +### end + +### bashbox_interpreter_core_set_o_keyword_shows_as_k +# set -o keyword shows as k +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -o keyword; echo $-; set -o | grep -E '^(keyword|noexec) ' +### expect +hkBc +keyword on +noexec off +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-just-bash-compat.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-just-bash-compat.test.sh new file mode 100644 index 000000000..b892ee413 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-just-bash-compat.test.sh @@ -0,0 +1,403 @@ +# BashBox just-bash-compat cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_just_bash_compat_read_consumes_stdin_line_by_line +# read consumes stdin line by line +printf "a\nb\n" | while read l; do echo "<$l>"; done +### expect + + +### end + +### bashbox_just_bash_compat_loop_reads_redirected_file +# loop reads redirected file +printf "1\n2\n" > in; while read l; do echo $l | cat; done < in +### expect +1 +2 +### end + +### bashbox_just_bash_compat_nested_reads_share_stdin +# nested reads share stdin +printf "1\n2\n" | { { read a; }; read b; echo $a$b; } +### expect +12 +### end + +### bashbox_just_bash_compat_read_returns_1_on_unterminated_last_line +# read returns 1 on unterminated last line +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf "x" | { read v; echo "$?:$v"; } +### expect +1:x +### end + +### bashbox_just_bash_compat_pipe_into_if +# pipe into if +echo hi | if true; then cat; fi +### expect +hi +### end + +### bashbox_just_bash_compat_loop_output_goes_through_the_pipe +# loop output goes through the pipe +for i in b a; do echo $i; done | sort +### expect +a +b +### end + +### bashbox_just_bash_compat_loop_redirected_to_dev_null +# loop redirected to /dev/null +while true; do echo x; break; done >/dev/null; echo ok +### expect +ok +### end + +### bashbox_just_bash_compat_group_redirected_to_file_with_2_1 +# group redirected to file with 2>&1 +{ echo o; echo e >&2; } > f 2>&1; cat f +### expect +o +e +### end + +### bashbox_just_bash_compat_stderr_to_dev_null +# stderr to /dev/null +cat nope 2>/dev/null; echo rc=$? +### expect +rc=1 +### end + +### bashbox_just_bash_compat_stderr_into_the_pipe +# stderr into the pipe +ls nope 2>&1 | grep -c nope +### expect +1 +### end + +### bashbox_just_bash_compat_stdout_to_stderr +# stdout to stderr +echo e >&2 2>/dev/null; echo done +### expect +done +### end + +### bashbox_just_bash_compat_missing_input_file_skips_the_command +# missing input file skips the command +cat < nofile 2>/dev/null; echo rc=$? +### expect +rc=1 +### end + +### bashbox_just_bash_compat_break_exits_loop_with_status_0 +# break exits loop with status 0 +while :; do false; break; done; echo $? +### expect +0 +### end + +### bashbox_just_bash_compat_bare_assignment_status +# bare assignment status +false; x=1; echo $? +### expect +0 +### end + +### bashbox_just_bash_compat_assignment_takes_substitution_status +# assignment takes substitution status +x=$(false); echo $? +### expect +1 +### end + +### bashbox_just_bash_compat_quoted_keeps_words +# quoted $@ keeps words +set -- "a b" c; printf "[%s]" "$@"; echo +### expect +[a b][c] +### end + +### bashbox_just_bash_compat_empty_quoted_vanishes +# empty quoted $@ vanishes +set --; printf "[%s]" "$@" x; echo +### expect +[x] +### end + +### bashbox_just_bash_compat_joins_with_surrounding_text +# $@ joins with surrounding text +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- a b; printf "[%s]" "x$@y"; echo +### expect +[xa][by] +### end + +### bashbox_just_bash_compat_quoted_array_expansion +# quoted array expansion +a=("x y" z); printf "[%s]" "${a[@]}" "${a[*]}"; echo +### expect +[x y][z][x y z] +### end + +### bashbox_just_bash_compat_1_idiom +# ${1+"$@"} idiom +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- "a b" c; for w in "${1+"$@"}"; do echo "[$w]"; done +### expect +[a b] +[c] +### end + +### bashbox_just_bash_compat_positional_slice +# positional slice +set -- a b c; echo "${@:2}" +### expect +b c +### end + +### bashbox_just_bash_compat_positional_beyond_9 +# positional beyond 9 +set -- 1 2 3 4 5 6 7 8 9 10 11; echo ${10} ${11} +### expect +10 11 +### end + +### bashbox_just_bash_compat_unquoted_variable_is_split +# unquoted variable is split +x="a b"; printf "[%s]" $x "$x"; echo +### expect +[a][b][a b] +### end + +### bashbox_just_bash_compat_unquoted_empty_variable_vanishes +# unquoted empty variable vanishes +e=; printf "[%s]" $e "$e" x; echo +### expect +[][x] +### end + +### bashbox_just_bash_compat_custom_ifs_splits_expansions_only +# custom IFS splits expansions only +IFS=:; x=a:b; printf "[%s]" $x; echo +### expect +[a][b] +### end + +### bashbox_just_bash_compat_command_word_is_split +# command word is split +C="echo hi"; $C there +### expect +hi there +### end + +### bashbox_just_bash_compat_default_and_alternative_operators +# default and alternative operators +unset u; e=; echo "[${u-d}][${u+a}][${e-d}][${e+a}][${e:-d}]" +### expect +[d][][][a][d] +### end + +### bashbox_just_bash_compat_cannot_assign_to_positional +# cannot assign to positional +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +: ${1:=x}; echo after +### expect +### end + +### bashbox_just_bash_compat_error_if_unset_stops_the_script +# error-if-unset stops the script +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a; echo ${zz:?boom}; echo after +### expect +a +### end + +### bashbox_just_bash_compat_glob_matches_directories_only_with +# glob matches directories only with */ +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +mkdir d1 d2; touch f1; for d in */; do echo $d; done +### expect +d1/ +d2/ +### end + +### bashbox_just_bash_compat_quoted_glob_stays_literal +# quoted glob stays literal +touch a.txt b.txt; echo *.txt "*.txt" \*.txt +### expect +a.txt b.txt *.txt *.txt +### end + +### bashbox_just_bash_compat_glob_skips_dotfiles +# glob skips dotfiles +touch .h v; echo * +### expect +v +### end + +### bashbox_just_bash_compat_glob_bracket_expression +# glob bracket expression +touch a1 a2 b1; echo a[12] [!a]1 +### expect +a1 a2 b1 +### end + +### bashbox_just_bash_compat_glob_in_a_directory_component +# glob in a directory component +mkdir -p p/x p/y; touch p/x/f p/y/f; echo p/*/f +### expect +p/x/f p/y/f +### end + +### bashbox_just_bash_compat_sed_append_keeps_leading_blanks +# sed append keeps leading blanks +echo x | sed "a\ indented" +### expect +x + indented +### end + +### bashbox_just_bash_compat_sed_addresses_and_commands +# sed addresses and commands +printf "1\n2\n3\n" | sed -n 2p; printf "1\n2\n3\n" | sed 2d; printf "a\nb\n" | sed "1c X" +### expect +2 +1 +3 +X +b +### end + +### bashbox_just_bash_compat_sed_range_and_negation +# sed range and negation +printf "x\nstart\ny\nend\nz\n" | sed -n "/start/,/end/p"; printf "1\n2\n3\n" | sed "\$!d" +### expect +start +y +end +3 +### end + +### bashbox_just_bash_compat_sed_multiple_commands +# sed multiple commands +echo abc | sed "s/a/A/;s/c/C/" +### expect +AbC +### end + +### bashbox_just_bash_compat_sed_bre_groups_and_escaped_backslash +# sed BRE groups and escaped backslash +echo ab | sed "s/\(a\)\(b\)/\2\1/"; echo ab | sed "s/\(a\)/\\\\\1/" +### expect +ba +\ab +### end + +### bashbox_just_bash_compat_sed_nth_occurrence +# sed nth occurrence +echo aaa | sed s/a/X/2; echo aaa | sed s/a/X/2g +### expect +aXa +aXX +### end + +### bashbox_just_bash_compat_sed_n_and_hold_space +# sed N and hold space +printf "1\n2\n3\n4\n" | sed "N;s/\n/,/"; printf "1\n2\n" | sed -n "h;n;G;p" +### expect +1,2 +3,4 +2 +1 +### end + +### bashbox_just_bash_compat_head_and_tail_n_shorthand +# head and tail -N shorthand +printf "1\n2\n3\n" | head -2; printf "1\n2\n3\n" | tail -2 +### expect +1 +2 +2 +3 +### end + +### bashbox_just_bash_compat_tr_octal_escapes +# tr octal escapes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a | tr a "\101" +### expect +A +### end + +### bashbox_just_bash_compat_cp_f_and_n +# cp -f and -n +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a > f; echo b > g; cp -f f h && cat h; cp -n g f; cat f +### expect +a +a +### end + +### bashbox_just_bash_compat_yes_is_finite_in_a_pipe +# yes is finite in a pipe +yes | head -2; yes ab | head -1 +### expect +y +y +ab +### end + +### bashbox_just_bash_compat_realpath +# realpath +mkdir -p r/s; cd r; realpath s . | sed "s|.*/||" +### expect +s +r +### end + +### bashbox_just_bash_compat_mktemp_creates_a_private_file +# mktemp creates a private file +f=$(mktemp); test -f "$f" && echo file; d=$(mktemp -d); test -d "$d" && echo dir +### expect +file +dir +### end + +### bashbox_just_bash_compat_declare_a_compound_assignment_keeps_quoted_values +# declare -A compound assignment keeps quoted values +declare -A m=([k]="hello world" [j]=x); echo "${m[k]}|${m[j]}|${#m[@]}" +### expect +hello world|x|2 +### end + +### bashbox_just_bash_compat_local_a_compound_assignment +# local -A compound assignment +f(){ local -A m=([a]=1 [b]="2 3"); echo "${m[a]}${m[b]}"; }; f +### expect +12 3 +### end + +### bashbox_just_bash_compat_keyed_elements_in_an_indexed_array +# keyed elements in an indexed array +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(x [5]=y z); echo ${!a[@]} ${a[6]} +### expect +0 5 6 z +### end + +### bashbox_just_bash_compat_array_keys_are_expanded +# array keys are expanded +k=key; declare -A m=([$k]="v w"); echo "${m[key]}" +### expect +v w +### end + +### bashbox_just_bash_compat_readonly_array_declaration +# readonly array declaration +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +readonly -a r=(1 2); echo ${r[1]} +### expect +2 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-lexer.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-lexer.test.sh new file mode 100644 index 000000000..35f532161 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-lexer.test.sh @@ -0,0 +1,260 @@ +# BashBox lexer cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_lexer_comments +# comments +echo a # not printed +# whole line +echo b +### expect +a +b +### end + +### bashbox_lexer_trailing_whitespace +# trailing whitespace +echo a +### expect +a +### end + +### bashbox_lexer_line_continuation_between_words +# line continuation between words +echo a \ + b +### expect +a b +### end + +### bashbox_lexer_line_continuation_inside_a_word +# line continuation inside a word +echo a\ +b +### expect +ab +### end + +### bashbox_lexer_trailing_backslash +# trailing backslash +echo a\ +### expect +a\ +### end + +### bashbox_lexer_newlines_inside_quotes +# newlines inside quotes +echo 'a +b' "c +d" +### expect +a +b c +d +### end + +### bashbox_lexer_escapes_inside_backticks +# escapes inside backticks +echo `echo \`echo hi\`` +### expect +hi +### end + +### bashbox_lexer_parens_inside_quoted_command_substitution +# parens inside quoted command substitution +echo $(echo ")") $(echo "a\"b") $(echo 'x)') +### expect +) a"b x) +### end + +### bashbox_lexer_lone_dollar_signs +# lone dollar signs +echo $% a$ $ +### expect +$% a$ $ +### end + +### bashbox_lexer_nested_braces_in_parameter_expansion +# nested braces in parameter expansion +echo ${x:-{a}} +### expect +{a} +### end + +### bashbox_lexer_empty_braces_are_a_word +# empty braces are a word +echo {} +### expect +{} +### end + +### bashbox_lexer_bang_followed_by_text_is_a_word +# bang followed by text is a word +echo !x +### expect +!x +### end + +### bashbox_lexer_double_brackets_followed_by_text_are_a_word +# double brackets followed by text are a word +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo ]]x +### expect +]]x +### end + +### bashbox_lexer_nested_subshell_closing_with +# nested subshell closing with )) +( (echo hi)) +### expect +hi +### end + +### bashbox_lexer_nested_parens_in_arithmetic_command +# nested parens in arithmetic command +(( ((1+2)) == 3 && (1+(2)) == 3 )) && echo yes +### expect +yes +### end + +### bashbox_lexer_is_a_shift_inside +# << is a shift inside (( )) +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +(( x = 1 << 2 )) +echo $x +### expect +4 +### end + +### bashbox_lexer_inside_c_style_for_header +# ;; inside C-style for header +for ((;;)); do echo x; break; done +### expect +x +### end + +### bashbox_lexer_parens_inside_in_double_quotes +# parens inside $(...) in double quotes +echo "a $(echo ")") b" +### expect +a ) b +### end + +### bashbox_lexer_backticks_in_double_quotes +# backticks in double quotes +echo "a `echo ")"` b" +### expect +a ) b +### end + +### bashbox_lexer_quoted_brace_in +# quoted brace in ${...} +echo ${x:-'}'} +### expect +} +### end + +### bashbox_lexer_escaped_quote_in_ansi_c_quoting +# escaped quote in ANSI-C quoting +echo $'a\'b' +### expect +a'b +### end + +### bashbox_lexer_nested_parens_in +# nested parens in $((...)) +echo $((1+(2))) foo +### expect +3 foo +### end + +### bashbox_lexer_single_quoted +# single quoted +x=1; cat << 'EOF' +$x +EOF +### expect +$x +### end + +### bashbox_lexer_double_quoted +# double quoted +x=1; cat <<"EOF" +$x +EOF +### expect +$x +### end + +### bashbox_lexer_backslash_escaped +# backslash escaped +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; cat <<\E\OF +$x +EOF +### expect +$x +### end + +### bashbox_lexer_partly_quoted +# partly quoted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=1; cat < + + +p q + +pq +### end + +### bashbox_shell_variables_a_pipeline_sets_one_status_per_command +# a pipeline sets one status per command +true | false | true; echo "${PIPESTATUS[*]}" ${#PIPESTATUS[@]}; declare -p PIPESTATUS +### expect +0 1 0 3 +declare -a PIPESTATUS=([0]="0") +### end + +### bashbox_shell_variables_a_single_command_and_a_negated_one_set_it_too +# a single command and a negated one set it too +false; echo ${PIPESTATUS[@]}; ! true; echo ${PIPESTATUS[@]}; f() { return 3; }; f; echo ${PIPESTATUS[@]} +### expect +1 +0 +3 +### end + +### bashbox_shell_variables_an_assignment_and_a_subshell_each_set_it +# an assignment, ((...)), [[...]] and a subshell each set it +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +false | true; x=$(false); echo ${PIPESTATUS[@]}; (( 0 )); echo ${PIPESTATUS[@]}; [[ a == a ]]; echo ${PIPESTATUS[@]}; (exit 3); echo ${PIPESTATUS[@]} +### expect +1 +1 +0 +3 +### end + +### bashbox_shell_variables_other_compound_commands_and_definitions_leave_the_last_one_i +# other compound commands and definitions leave the last one inside them +false | true; { false | true; }; echo ${PIPESTATUS[@]}; false | true; case x in y) ;; esac; echo ${PIPESTATUS[@]}; false | true; f() { :; }; echo ${PIPESTATUS[@]} +### expect +1 0 +1 0 +1 0 +### end + +### bashbox_shell_variables_a_substitution_sees_the_status_from_before_it +# a substitution sees the status from before it +false | true; echo $(echo ${PIPESTATUS[@]}) +### expect +1 0 +### end + +### bashbox_shell_variables_pipefail_changes_but_not_pipestatus_and_the_shell_overwrites +# pipefail changes $? but not PIPESTATUS, and the shell overwrites it even when readonly +set -o pipefail; false | true; echo $? ${PIPESTATUS[@]}; PIPESTATUS=(9 9); echo ${PIPESTATUS[@]}; readonly PIPESTATUS; true | false; echo ${PIPESTATUS[@]} +### expect +1 1 0 +0 +0 1 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-glob.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-glob.test.sh new file mode 100644 index 000000000..b4bfc67ff --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-glob.test.sh @@ -0,0 +1,89 @@ +# BashBox shopt-glob cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_shopt_glob_nullglob_drops_a_pattern_that_matches_nothing +# nullglob drops a pattern that matches nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +shopt -s nullglob; echo a *.nope b; x=(*.nope); echo ${#x[@]}; echo "*.nope" +### expect +a b +0 +*.nope +### end + +### bashbox_shopt_glob_dotglob_lets_match_dotfiles +# dotglob lets * match dotfiles +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +shopt -s dotglob; echo *; echo .*; shopt -u dotglob; echo *; echo .* +### expect +.hid C.TXT a.txt b.txt d +.hid +C.TXT a.txt b.txt d +.hid +### end + +### bashbox_shopt_glob_nocaseglob +# nocaseglob +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +shopt -s nocaseglob; echo *.txt; echo [a-c]*; echo c.txt +### expect +C.TXT a.txt b.txt +C.TXT a.txt b.txt +c.txt +### end + +### bashbox_shopt_glob_globstar_makes_recurse +# globstar makes ** recurse +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +shopt -s globstar; echo **; echo **/*.txt; echo d/**; echo d/**/; shopt -u globstar; echo **/*.txt +### expect +C.TXT a.txt b.txt d d/e d/e/y.txt d/x.txt +a.txt b.txt d/e/y.txt d/x.txt +d/ d/e d/e/y.txt d/x.txt +d/ d/e/ +d/x.txt +### end + +### bashbox_shopt_glob_a_literal_last_part_must_exist +# a literal last part must exist +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +echo */x.txt */nope.txt; echo d/*/; echo "*".txt \*.txt +### expect +d/x.txt */nope.txt +d/e/ +*.txt *.txt +### end + +### bashbox_shopt_glob_extglob_patterns_in_pathnames +# extglob patterns in pathnames +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +shopt -s extglob +echo !(*.txt); echo @(a|b).txt; echo *(a).txt; echo +([a-c]).txt; echo ?(a).txt; echo !(d|*.txt|C*) +echo "@(a)".txt; x='@(a|b).txt'; echo $x; echo "$x"; echo @(nomatch) +### expect +C.TXT d +a.txt b.txt +a.txt +a.txt b.txt +a.txt +!(d|*.txt|C*) +@(a).txt +a.txt b.txt +@(a|b).txt +@(nomatch) +### end + +### bashbox_shopt_glob_without_extglob_the_parentheses_are_literal +# without extglob the parentheses are literal +mkdir -p d/e; touch a.txt b.txt .hid C.TXT d/x.txt d/e/y.txt +x='@(a).txt'; echo $x +shopt -s extglob +echo $x +### expect +@(a).txt +a.txt +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-pattern.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-pattern.test.sh new file mode 100644 index 000000000..58188e9cc --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt-pattern.test.sh @@ -0,0 +1,144 @@ +# BashBox shopt-pattern cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_shopt_pattern_always_understands_extglob +# [[ ]] always understands extglob +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=abc; [[ $x == @(a|b)* ]] && echo y1; [[ $x == +([a-c]) ]] && echo y2; [[ $x == !(a*) ]] || echo y3; [[ "" == !(x) ]] && echo y4; [[ "a|b" == @(a\|b) ]] && echo y5; [[ abab == +(ab|a) ]] && echo y6; [[ b == *(a)b ]] && echo y7; [[ ab == ?(a)b ]] && echo y8 +### expect +y1 +y2 +y3 +y4 +y5 +y6 +y7 +y8 +### end + +### bashbox_shopt_pattern_case_needs_shopt_s_extglob +# case needs shopt -s extglob +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +p='@(abc)'; case abc in $p) echo no;; *) echo plain;; esac +shopt -s extglob +case abc in $p) echo yes;; esac; case abc in @(abc)) echo yes;; esac; case a in !(a)*) echo m1;; esac +### expect +plain +yes +yes +m1 +### end + +### bashbox_shopt_pattern_pattern_removal_and_substitution_with_extglob +# pattern removal and substitution with extglob +shopt -s extglob +x=abc; echo "${x//*(z)/-}|${x/*(z)/-}|${x//!(b)/-}|${x/!(b)/-}|${x#!(b)}|${x##!(b)}|${x%!(b)}|${x%%!(b)}|${x/#!(a)/-}|${x/%!(c)/-}" +echo ${x/@(b|c)/X} ${x//[ac]/Y}; y=aXbXc; echo ${y//!(X)/-} ${x//?(b)/-} +x=aab; echo ${x##+(a)} ${x#+(a)} ${x%%+(b)} ${x/+(a)/-}; z=a; echo "${z//!(a)/-}" "${z/#!(b)/-}" "${x/%!(z)/-}" "${x/!(a*)/-}" "${x/!(*)/-}" +### expect +-a-b-c|-abc|-|-|abc||abc||-|- +aXc YbY +- -a--c +b ab aa -b +-a - - -aab aab +### end + +### bashbox_shopt_pattern_quoted_parts_of_a_pattern_match_literally +# quoted parts of a pattern match literally +[[ abc == "a"* ]] && echo q1; [[ abc == "a*" ]] || echo q2; case "a*" in "a*") echo q3;; esac; case ab in "a"?) echo q4;; esac +p='a*'; [[ abc == $p ]] && echo q5; [[ abc == "$p" ]] || echo q6; [[ x != "x" ]] || echo q7 +### expect +q1 +q2 +q3 +q4 +q5 +q6 +q7 +### end + +### bashbox_shopt_pattern_nocasematch_covers_case_and_substitution_not_removal +# nocasematch covers case, [[ ]] and substitution, not removal +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=ABC; shopt -s nocasematch +case ABC in a*) echo m1;; esac; [[ ABC == ab? ]] && echo m2; [[ ABC =~ ^ab ]] && echo m3; [[ ABC = abc ]] && echo m4; echo ${x#a} ${x/b/z} ${x%c} ${x//b/z} ${x/#a/q}; [[ $x != abc ]]; echo $? +shopt -u nocasematch; [[ ABC == abc ]] || echo m5 +### expect +m1 +m2 +m3 +m4 +ABC AzC ABC AzC qBC +1 +m5 +### end + +### bashbox_shopt_pattern_bracket_expressions_in_removal_patterns +# bracket expressions in removal patterns +x=ABC; echo ${x#[AB]} ${x##[[:upper:]]*} ${x%[!C]C} ${x/[z-a]/q} ${x#[z-a]} +### expect +BC A ABC ABC +### end + +### bashbox_shopt_pattern_array_and_positional_operations_apply_per_element +# array and positional operations apply per element +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- ab ac; echo "${@#a}" "${@/c/x}"; a=(xa ya); echo "${a[@]%a}" "${a[*]^^}"; x=aab; echo ${x/q/z} ${x/#/-} ${x/%/-} "${x//b/\$}"; declare -A m=([k1]=a [k2]=b); for k in "${!m[@]}"; do echo "<$k>"; done +### expect +b c ab ax +x y XA YA +aab -aab aab- aa$ + + +### end + +### bashbox_shopt_pattern_quotes_inside_a_group +# quotes inside a group +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +[[ "b)" == @(a|'b)') ]] && echo q1; [[ 'a"' == @("a\"") ]] && echo q2; [[ 'a|' == @(a\|) ]] && echo q3 +### expect +q1 +q2 +q3 +### end + +### bashbox_shopt_pattern_an_unbalanced_group_from_a_variable_is_literal +# an unbalanced group from a variable is literal +p='@(a'; [[ '@(a' == $p ]] && echo lit +### expect +lit +### end + +### bashbox_shopt_pattern_a_negation_nested_in_another_group +# a negation nested in another group +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +[[ c == @(!(a)|b) ]] && echo y1; [[ a == @(!(a)) ]] || echo y2; [[ ab == !(x)? ]] && echo y3 +### expect +y1 +y2 +y3 +### end + +### bashbox_shopt_pattern_groups_next_to_a_negation +# groups next to a negation +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +[[ abab == !(x)+(ab) ]] && echo y1; [[ ab == @(a)!(x) ]] && echo y2; [[ b == ?(a)!(z) ]] && echo y3; [[ aab == *(a)!(z) ]] && echo y4; [[ ab == +(a|ab)!(z) ]] && echo y5; [[ aaa == !(z)*(a|aa) ]] && echo y6; [[ x == !(z)+(a) ]] || echo y7; [[ ab == !(x)+(a|b) ]] && echo y8 +### expect +y1 +y2 +y3 +y4 +y5 +y6 +y7 +y8 +### end + +### bashbox_shopt_pattern_no_match_leaves_the_value_alone +# no match leaves the value alone +shopt -s extglob +x=abc; echo ${x#!(*)} ${x/#!(*)/-} ${x//!(*)/-} ${x%%!(*)} +### expect +abc abc abc abc +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-shopt.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt.test.sh new file mode 100644 index 000000000..1f632abae --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-shopt.test.sh @@ -0,0 +1,70 @@ +# BashBox shopt cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_shopt_unknown_names_are_reported_but_the_rest_still_apply +# unknown names are reported but the rest still apply +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +shopt -s extglob nope nullglob; echo s=$?; shopt -p nullglob extglob; shopt -q nope; echo s=$? +### expect +s=1 +shopt -s nullglob +shopt -s extglob +s=1 +### end + +### bashbox_shopt_bad_flags +# bad flags +shopt -s -u x; echo s=$?; shopt -x; echo s=$?; shopt -sx; echo s=$? +### expect +s=1 +s=2 +s=2 +### end + +### bashbox_shopt_o_with_a_bad_name +# -o with a bad name +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +shopt -so nope; echo s=$?; shopt -uo nope; echo s=$?; shopt -o nope; echo s=$?; shopt -po nope errexit; echo s=$? +### expect +s=0 +s=0 +s=1 +set +o errexit +s=1 +### end + +### bashbox_shopt_lastpipe_is_accepted +# lastpipe is accepted +shopt -s lastpipe; echo a | read v; echo "[$v]" +### expect +[a] +### end + +### bashbox_shopt_aliases_expand_only_with_expand_aliases_from_the_next_line_o +# aliases expand only with expand_aliases, from the next line on +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +alias e='echo hi' +e there +shopt -s expand_aliases +e there +alias echo='echo [e]'; echo x; x=1 e y > f; cat f +alias c='cat'; c < f; sort -o f f; cat f +### expect +a +b +### end + +### bashbox_sort_c_on_sorted_input +# -c on sorted input +printf 'a\nb\nb\n' | sort -c +### expect +### end + +### bashbox_sort_m_merges_sorted_inputs +# -m merges sorted inputs +printf 'a\nc\ne\n' > f1; printf 'b\nc\nd\n' > f2; sort -m f1 f2 +### expect +a +b +c +c +d +e +### end + +### bashbox_sort_m_does_not_sort +# -m does not sort +printf 'b\na\n' > f1; printf 'c\n' > f2; sort -m f1 f2 +### expect +b +a +c +### end + +### bashbox_sort_m_with_keys_and_reverse +# -m with keys and reverse +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '3 a\n1 b\n' > f1; printf '2 c\n' > f2; sort -m -k1,1nr f1 f2 +### expect +3 a +2 c +1 b +### end + +### bashbox_sort_long_options +# long options +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'b:2\na:10\n' | sort --field-separator=: --key=2 --numeric-sort --reverse +### expect +a:10 +b:2 +### end + +### bashbox_sort_sort_selects_the_comparison +# --sort selects the comparison +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '10\n9\n' | sort --sort=num +### expect +9 +10 +### end + +### bashbox_sort_ignored_performance_options +# ignored performance options +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'b\na\n' | sort -S 1M -T /tmp --parallel=2 --compress-program=gzip +### expect +a +b +### end + +### bashbox_sort_r_groups_equal_lines +# -R groups equal lines +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\na\nb\n' | sort -R | uniq | sort +### expect +a +b +### end + +### bashbox_sort_d_is_compatible_with_v +# -d is compatible with -V +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a-2\na-10\n' | sort -dV +### expect +a-2 +a-10 +### end + +### bashbox_sort_r_with_f +# -R with -f +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nA\nb\na\n' | sort -fR | tr A a | uniq | sort +### expect +a +b +### end + +### bashbox_sort_the_same_tab_twice +# the same tab twice +printf 'b:1\na:2\n' | sort -t: -t: -k2 +### expect +b:1 +a:2 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-stat.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-stat.test.sh new file mode 100644 index 000000000..69396acf4 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-stat.test.sh @@ -0,0 +1,19 @@ +# BashBox stat cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_stat_name_needing_double_quotes +# name needing double quotes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf x > "a'b c"; stat -c %N "a'b c" +### expect +"a'b c" +### end + +### bashbox_stat_name_needing_escapes +# name needing escapes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf x > $'a\nb'; stat -c %N $'a\nb' +### expect +'a'$'\n''b' +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-syntax-error.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-syntax-error.test.sh new file mode 100644 index 000000000..565a365c6 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-syntax-error.test.sh @@ -0,0 +1,113 @@ +# BashBox syntax-error cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_syntax_error_eval_reports_and_returns_2 +# eval reports and returns 2 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +eval fi; echo $? +### expect +2 +### end + +### bashbox_syntax_error_a_sourced_file_reports_under_its_name_and_returns_2 +# a sourced file reports under its name and returns 2 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo 'if then' > bad.sh; source ./bad.sh; echo $? +### expect +2 +### end + +### bashbox_syntax_error_a_backquoted_substitution_is_parsed_when_it_runs_and_fails_w +# a backquoted substitution is parsed when it runs and fails with 2 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=`fi`; echo "[$x] $?" +### expect +[] 2 +### end + +### bashbox_syntax_error_the_exit_trap_reports_its_own_syntax_error +# the EXIT trap reports its own syntax error +trap fi EXIT; echo a +### expect +a +### end + +### bashbox_syntax_error_the_err_trap_reports_its_own_syntax_error +# the ERR trap reports its own syntax error +trap fi ERR; false; echo $? +### expect +1 +### end + +### bashbox_syntax_error_the_return_trap_reports_its_own_syntax_error +# the RETURN trap reports its own syntax error +f(){ trap fi RETURN; }; f; echo $? +### expect +0 +### end + +### bashbox_syntax_error_a_case_pattern +# a case pattern +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +x=$(case a in a) echo A;; esac); echo "[$x]" +### expect +[A] +### end + +### bashbox_syntax_error_a_case_pattern_in_double_quotes +# a case pattern in double quotes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo "$(case b in a) echo A;; b) echo B;; esac)" +### expect +B +### end + +### bashbox_syntax_error_a_comment +# a comment +x=$( # comment with ) +echo hi); echo "[$x]" +### expect +[hi] +### end + +### bashbox_syntax_error_a_comment_after_a_command +# a comment after a command +x=$(echo a #) +); echo $x +### expect +a +### end + +### bashbox_syntax_error_a_here_document +# a here-document +x=$(cat <out 2>&1 out 2>&1 < in; + x=1 y= z+=2 +} +### end + +### bashbox_type_printer_pipelines_and_or_lists_and_background_jobs +# pipelines, |&, !, and-or lists and background jobs +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +g() { echo a | grep b |& cat; ! true && false || echo x; sleep 1 & echo bg; } +type g +### expect +g is a function +g () +{ + echo a | grep b 2>&1 | cat; + ! true && false || echo x; + sleep 1 & echo bg +} +### end + +### bashbox_type_printer_a_trailing_and_a_list_of_background_jobs +# a trailing & and a list of background jobs +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +d() { a & } +e() { a & +b & } +type d e +### expect +d is a function +d () +{ + a & +} +e is a function +e () +{ + a & b & +} +### end + +### bashbox_type_printer_if_elif_and_else_nest_like_bash_stores_them +# if, elif and else nest like bash stores them +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +h() { if a; then b; elif c; then d; else e; fi; } +type h +### expect +h is a function +h () +{ + if a; then + b; + else + if c; then + d; + else + e; + fi; + fi +} +### end + +### bashbox_type_printer_for_a_bare_for_while_and_until +# for, a bare for, while and until +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +h() { for i in 1 2; do echo $i; done; for j; do :; done; while x; do y; done; until x; do y; done; } +type h +### expect +h is a function +h () +{ + for i in 1 2; + do + echo $i; + done; + for j in "$@"; + do + :; + done; + while x; do + y; + done; + until x; do + y; + done +} +### end + +### bashbox_type_printer_case_with_alternatives_fallthrough_and_an_empty_body +# case with alternatives, fallthrough and an empty body +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +k() { case $1 in a|b) echo ab;; c) echo c;& d) ;;& *) echo def; esac; case x in (a) ;; esac; case w in esac; } +type k +### expect +k is a function +k () +{ + case $1 in + a | b) + echo ab + ;; + c) + echo c + ;& + d) + + ;;& + *) + echo def + ;; + esac; + case x in + a) + + ;; + esac; + case w in + esac +} +### end + +### bashbox_type_printer_subshells_groups_arithmetic_and_conditionals +# subshells, groups, arithmetic and conditionals +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +k() { ( sub; shell ); { grp; }; (( x++ )); ((y=1)); [[ -n $a && ( $b == c* || ! -f x ) ]]; [[ x ]]; [[ ! ( a == b ) ]]; [[ (a) ]]; } +type k +### expect +k is a function +k () +{ + ( sub; + shell ); + { + grp + }; + (( x++ )); + ((y=1)); + [[ -n $a && ( $b == c* || ! -f x ) ]]; + [[ -n x ]]; + [[ ! ( a == b ) ]]; + [[ ( -n a ) ]] +} +### end + +### bashbox_type_printer_c_style_for_keeps_each_part_as_written_empty_parts_read_1 +# C-style for keeps each part as written, empty parts read 1 +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a() { for ((i=0;i<3;i++)); do echo; done; for (( i = 0 ; i < 3 ; i++ )); do :; done; for ((;;)); do break; done; } +type a +### expect +a is a function +a () +{ + for ((i=0; i<3; i++)) + do + echo; + done; + for ((i = 0 ; i < 3 ; i++ )) + do + :; + done; + for ((1; 1; 1)) + do + break; + done +} +### end + +### bashbox_type_printer_a_subshell_body +# a subshell body +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +m() ( echo subshell-body ) +type m +### expect +m is a function +m () +{ + ( echo subshell-body ) +} +### end + +### bashbox_type_printer_a_compound_body_that_is_not_a_group +# a compound body that is not a group +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +f() if true; then :; fi +g() for i in a; do :; done 2>/dev/null +type f g +### expect +f is a function +f () +{ + if true; then + :; + fi +} +g is a function +g () +{ + for i in a; + do + :; + done 2> /dev/null +} +### end + +### bashbox_type_printer_here_documents_follow_the_line_that_opens_them +# here-documents follow the line that opens them +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +n() { cat < f + lit + Q +echo after; } +type n +### expect +n is a function +n () +{ + cat < f +lit +Q + + echo after +} +### end + +### bashbox_type_printer_a_here_document_ending_the_body +# a here-document ending the body +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +c() { cat <f; echo hi +one +A +two +B +} +w() { cat < f +one +A +two +B + + echo hi +} +w is a function +w () +{ + cat < /dev/null 2>&1 +type q +### expect +q is a function +q () +{ + echo a +} > /dev/null 2>&1 +### end + +### bashbox_type_printer_comments_and_continuations_disappear +# comments and continuations disappear +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +t() { echo # comment +} +v() { + # leading comment + echo one # trailing + echo "multi +line" \ + cont +} +type t v +### expect +t is a function +t () +{ + echo +} +v is a function +v () +{ + echo one; + echo "multi +line" cont +} +### end + +### bashbox_type_printer_quoting_is_kept_as_written +# quoting is kept as written +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +j() { echo a\ b "c\"d" 'e' \$x x=1; } +type j +### expect +j is a function +j () +{ + echo a\ b "c\"d" 'e' \$x x=1 +} +### end + +### bashbox_type_printer_declare_f_prints_every_function_sorted +# declare -f prints every function, sorted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +b() { :; } +a() { echo; } +declare -f +### expect +a () +{ + echo +} +b () +{ + : +} +### end + +### bashbox_type_printer_declare_f_with_names_failing_quietly_for_a_missing_one +# declare -f with names, failing quietly for a missing one +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +b() { :; } +declare -f b nope; echo "s=$?" +### expect +b () +{ + : +} +s=1 +### end + +### bashbox_type_printer_declare_f_lists_names +# declare -F lists names +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +b() { :; } +a() { :; } +declare -F; declare -F b nope a; echo "s=$?" +### expect +declare -f a +declare -f b +b +a +s=1 +### end + +### bashbox_type_printer_type_reports_each_name +# type reports each name +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +b() { :; } +type b nope; echo "s=$?"; type -t b +### expect +b is a function +b () +{ + : +} +s=1 +function +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-unexpand.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-unexpand.test.sh new file mode 100644 index 000000000..893d5144c --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-unexpand.test.sh @@ -0,0 +1,115 @@ +# BashBox unexpand cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_unexpand_single_space_before_stop +# single space before stop +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abcdefg h\n' | unexpand -a +### expect +abcdefg h +### end + +### bashbox_unexpand_single_blank_becomes_tab +# single blank becomes tab +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abcdefg \tx\n' | unexpand -a +### expect +abcdefg x +### end + +### bashbox_unexpand_list +# list +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c\n' | unexpand -t 2,6 +### expect + a b c +### end + +### bashbox_unexpand_list_exhausted +# list exhausted +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c d\n' | unexpand -t 2,6 +### expect + a b c d +### end + +### bashbox_unexpand_extend +# extend +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c d\n' | unexpand -t 2,/3 +### expect + a b c d +### end + +### bashbox_unexpand_increment +# increment +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c d\n' | unexpand -t 2,+3 +### expect + a b c d +### end + +### bashbox_unexpand_obsolete_list +# obsolete list +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c\n' | unexpand -2,6 +### expect + a b c +### end + +### bashbox_unexpand_obsolete_trailing_comma +# obsolete trailing comma +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' a b c\n' | unexpand -2,6, +### expect + a b c +### end + +### bashbox_unexpand_trailing_blanks_without_newline +# trailing blanks without newline +printf 'a ' | unexpand -a | od -c +### expect +0000000 a \t +0000002 +### end + +### bashbox_unexpand_non_blank_stops_leading_conversion +# non-blank stops leading conversion +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'x y\n' | unexpand +### expect +x y +### end + +### bashbox_unexpand_tab_at_stop +# tab at stop +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '\t\t a\n' | unexpand -t 4 +### expect + a +### end + +### bashbox_unexpand_spaces_then_tab +# spaces then tab +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf ' \ta\n' | unexpand +### expect + a +### end + +### bashbox_unexpand_one_space_then_tab +# one space then tab +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abcdefg \t \tx\n' | unexpand -a +### expect +abcdefg x +### end + +### bashbox_unexpand_blank_past_last_stop +# blank past last stop +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abc d\n' | unexpand -t 2 +### expect +abc d +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-uniq.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-uniq.test.sh new file mode 100644 index 000000000..1378b66b3 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-uniq.test.sh @@ -0,0 +1,88 @@ +# BashBox uniq cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_uniq_c_counts_runs +# -c counts runs +printf 'a\na\nb\na\n' | uniq -c +### expect + 2 a + 1 b + 1 a +### end + +### bashbox_uniq_d_keeps_only_repeated_lines +# -d keeps only repeated lines +printf 'a\na\nb\n' | uniq -d +### expect +a +### end + +### bashbox_uniq_u_keeps_only_unique_lines +# -u keeps only unique lines +printf 'a\na\nb\n' | uniq -u +### expect +b +### end + +### bashbox_uniq_adds_a_missing_final_newline +# adds a missing final newline +printf 'x\nx' | uniq +### expect +x +### end + +### bashbox_uniq_empty_input +# empty input +printf '' | uniq +### expect +### end + +### bashbox_uniq_second_operand_is_the_output_file +# second operand is the output file +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\na\n' > in; uniq in out; cat out +### expect +a +### end + +### bashbox_uniq_i_ignores_case +# -i ignores case +printf 'a\nA\nb\n' | uniq -ic +### expect + 2 a + 1 b +### end + +### bashbox_uniq_f_skips_fields +# -f skips fields +printf 'x a\ny a\nz b\n' | uniq -f1 +### expect +x a +z b +### end + +### bashbox_uniq_f_past_the_last_field_compares_empty_keys +# -f past the last field compares empty keys +printf 'a b\nc b\n' | uniq -f 5 +### expect +a b +### end + +### bashbox_uniq_s_skips_bytes +# -s skips bytes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'xa\nya\nzb\n' | uniq --skip-chars=1 +### expect +xa +zb +### end + +### bashbox_uniq_w_compares_a_prefix +# -w compares a prefix +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'ab1\nab2\nac\n' | uniq -w2 +### expect +ab1 +ac +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-utf8.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-utf8.test.sh new file mode 100644 index 000000000..9c1bd0c4a --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-utf8.test.sh @@ -0,0 +1,78 @@ +# BashBox utf8 cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_utf8_length_counts_characters +# length counts characters +x='héllo wörld'; echo ${#x}; y='日本語'; echo ${#y} +### expect +11 +3 +### end + +### bashbox_utf8_array_element_length +# array element length +a=('héllo' 'ö'); echo "${#a[0]} ${#a[1]} ${#a[@]}" +### expect +5 1 2 +### end + +### bashbox_utf8_positional_length +# positional length +set -- 'é' 'ab'; echo ${#1} ${#2} +### expect +1 2 +### end + +### bashbox_utf8_substring_by_character +# substring by character +x='héllo'; echo "${x:1:2}|${x: -3}|${x:0:1}|${x:4}|${x:(-4):2}" +### expect +él|llo|h|o|él +### end + +### bashbox_utf8_substring_of_wide_characters +# substring of wide characters +x='日本語'; echo "${x:1} ${x: -1:1}" +### expect +本語 語 +### end + +### bashbox_utf8_invalid_utf_8_counts_bytes +# invalid UTF-8 counts bytes +x=$'\xff\xfe'; echo ${#x}; y=$'a\xffb'; echo ${#y} "${y:2}" +### expect +2 +3 b +### end + +### bashbox_utf8_patterns_match_characters +# patterns match characters +x='héllo'; echo "${x#?}|${x%??}|${x/?/X}|${x//[é]/E}|${x/#h?/Y}" +### expect +éllo|hél|Xéllo|hEllo|Yllo +### end + +### bashbox_utf8_case_and_patterns +# case and [[ ]] patterns +x='héllo'; case $x in h?llo) echo case;; esac; [[ $x == h?llo ]] && echo glob; [[ $x =~ ^h.llo$ ]] && echo regex +### expect +case +glob +regex +### end + +### bashbox_utf8_filename_globbing_by_character +# filename globbing by character +touch é1 ab1; echo ?1 +### expect +é1 +### end + +### bashbox_utf8_patterns_on_invalid_utf_8 +# patterns on invalid UTF-8 +x=$'\xffa'; echo "${x#?}"; case $x in ?a) echo case;; esac +### expect +a +case +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-wc.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-wc.test.sh new file mode 100644 index 000000000..a0db97347 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-wc.test.sh @@ -0,0 +1,11 @@ +# BashBox wc cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_wc_stdin_reserves_seven_columns +# stdin reserves seven columns +echo hi | wc; echo hi | wc -lc +### expect + 1 1 3 + 1 3 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-word-expander.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-word-expander.test.sh new file mode 100644 index 000000000..b2735fea8 --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-word-expander.test.sh @@ -0,0 +1,310 @@ +# BashBox word-expander cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_word_expander_braced_positional_and_counts +# braced positional and counts +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +set -- a b; echo ${1} ${#} ${#@} ${#*} +### expect +a 2 2 2 +### end + +### bashbox_word_expander_positional_slices +# positional slices +set -- a b c; echo ${@:2} ${*: -1} +### expect +b c c +### end + +### bashbox_word_expander_name_i_is_not_an_array_reference +# $name[i] is not an array reference +a=(x y); echo $a[1] +### expect +x[1] +### end + +### bashbox_word_expander_bare_array_name_is_element_0 +# bare array name is element 0 +a=(x y); echo $a ${a} +### expect +x x +### end + +### bashbox_word_expander_substring_with_negative_offset_length +# substring with negative offset/length +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +s=hello; echo ${s: -2} ${s:1:-1} ${s: -3:2} "[${s: -10}]" ${s:1+1:2} +### expect +lo ell ll [] ll +### end + +### bashbox_word_expander_array_slices +# array slices +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +a=(1 2 3 4); echo ${a[@]: -2} ${a[@]:1:2} "[${a[@]: -9}]" +### expect +3 4 2 3 [] +### end + +### bashbox_word_expander_subscripts_are_arithmetic +# subscripts are arithmetic +a=(x y z); i=1; echo ${a[$i]} ${a[i]} ${a[i+1]} ${a[-1]} +### expect +y y z z +### end + +### bashbox_word_expander_associative_subscript_is_expanded +# associative subscript is expanded +declare -A m; m[k]=v; key=k; echo ${m[$key]} ${m[k]} +### expect +v v +### end + +### bashbox_word_expander_element_length +# element length +a=(foo bar); echo ${#a[1]} +### expect +3 +### end + +### bashbox_word_expander_keys_and_counts +# keys and counts +a=(b a); echo ${!a[@]} ${#a[@]} ${a[*]} +### expect +0 1 2 b a +### end + +### bashbox_word_expander_indirection +# indirection +r=x; x=val; echo "[${!r}]" +### expect +[val] +### end + +### bashbox_word_expander_indirection_to_an_element +# indirection to an element +a=(p q); r="a[1]"; echo ${!r} +### expect +q +### end + +### bashbox_word_expander_nested_default +# nested default +x=; echo ${x:-${y:-z}} +### expect +z +### end + +### bashbox_word_expander_element_default +# element default +a=(p q); echo ${a[0]:-d} ${a[5]:-d} +### expect +p d +### end + +### bashbox_word_expander_set_vs_null_tests +# set vs null tests +unset x; echo ${x-unset} ${x+set}; x=; echo ${x-unset} ${x+set} ${x:+nonempty} +### expect +unset +set +### end + +### bashbox_word_expander_empty_uses_default +# empty $@ uses default +set --; echo "[${@-x}] [${@:-y}]" +### expect +[x] [y] +### end + +### bashbox_word_expander_assign_default +# assign default +echo ${z=assigned} $z +### expect +assigned assigned +### end + +### bashbox_word_expander_assign_default_to_element +# assign default to element +echo ${a[1]:=x} ${a[1]} +### expect +x x +### end + +### bashbox_word_expander_error_if_unset_passes_a_set_value +# error-if-unset passes a set value +x=v; echo ${x?never} ${x:?never} +### expect +v v +### end + +### bashbox_word_expander_pattern_operand_is_expanded +# pattern operand is expanded +p=b; x=abc; echo ${x#*$p} +### expect +c +### end + +### bashbox_word_expander_quoted_pattern_characters_are_literal +# quoted pattern characters are literal +x='a*b'; echo ${x#*\*} ${x%"*"b} +### expect +b a +### end + +### bashbox_word_expander_prefix_suffix_removal +# prefix/suffix removal +x=a.b.c; echo ${x#*.} ${x##*.} ${x%.*} ${x%%.*} ${x#?} +### expect +b.c c a.b a .b.c +### end + +### bashbox_word_expander_anchored_replacement +# anchored replacement +x=abc; echo ${x/#a/X} ${x/%c/Y} ${x/b} +### expect +Xbc abY ac +### end + +### bashbox_word_expander_replacement_is_not_a_regex_template +# replacement is not a regex template +x=abc; r='\0$1'; echo ${x/b/$r} +### expect +a\0$1c +### end + +### bashbox_word_expander_replace_first_all +# replace first/all +x=abab; echo ${x/b/X} ${x//b/X} +### expect +aXab aXaX +### end + +### bashbox_word_expander_case_modification +# case modification +x=hello; echo ${x^} ${x^^} ${x,} ${x,,} +### expect +Hello HELLO hello hello +### end + +### bashbox_word_expander_nested_arithmetic_parens +# nested arithmetic parens +echo $(( ((1+2)) * 3 )) $(( (1+(2)) )) +### expect +9 3 +### end + +### bashbox_word_expander_quoted_parens_in +# quoted parens in $(...) +echo $(echo ")" "(" '(') $(echo "a)b\")") +### expect +) ( ( a)b") +### end + +### bashbox_word_expander_joins_with_first_ifs_char +# "$*" joins with first IFS char +set -- a b; IFS=:; echo "$*" +### expect +a:b +### end + +### bashbox_word_expander_trailing_backslash_pattern +# trailing backslash pattern +x="a\\"; p="\\"; echo ${x%$p} +### expect +a +### end + +### bashbox_word_expander_lone_or_unknown +# lone or unknown $ +echo a$%b $ +### expect +a$%b $ +### end + +### bashbox_word_expander_unset_variable_is_empty +# unset variable is empty +echo $nothing. +### expect +. +### end + +### bashbox_word_expander_double_quote_escapes +# double-quote escapes +echo "a\"b\$c\\d\q" +### expect +a"b$c\d\q +### end + +### bashbox_word_expander_backtick_keeps_other_backslashes +# backtick keeps other backslashes +x=`printf "%s" "a\qb"`; echo $x +### expect +a\qb +### end + +### bashbox_word_expander_nested_backticks +# nested backticks +x=`echo \`echo hi\``; echo $x +### expect +hi +### end + +### bashbox_word_expander_ifs_splitting_with_non_whitespace +# IFS splitting with non-whitespace +IFS=:; x=":a::b:"; printf "[%s]" $x; echo +### expect +[][a][][b] +### end + +### bashbox_word_expander_empty_unquoted_word_vanishes +# empty unquoted word vanishes +x=; printf "[%s]" $x a; echo +### expect +[a] +### end + +### bashbox_word_expander_empty_ifs_does_not_split +# empty IFS does not split +IFS=; x="a b"; printf "[%s]" $x; echo +### expect +[a b] +### end + +### bashbox_word_expander_whitespace_ifs_collapses +# whitespace IFS collapses +x=" a b "; printf "[%s]" $x; echo +### expect +[a][b] +### end + +### bashbox_word_expander_keeps_words +# "$@" keeps words +f(){ for x in "$@"; do echo "[$x]"; done; }; f a "b c" +### expect +[a] +[b c] +### end + +### bashbox_word_expander_escaped_comma_and_non_expanding_braces +# escaped comma and non-expanding braces +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo {a\,b,c} {a}b {abc} {1..c} +### expect +a,b c {a}b {abc} {1..c} +### end + +### bashbox_word_expander_descending_ranges +# descending ranges +echo {5..1} {c..a} +### expect +5 4 3 2 1 c b a +### end + +### bashbox_word_expander_stepped_ranges +# stepped ranges +echo {1..9..3} {a..e..2} {1..5..-2} +### expect +1 4 7 a c e 1 3 5 +### end diff --git a/crates/bashkit/tests/spec_cases/bash/bashbox-xargs.test.sh b/crates/bashkit/tests/spec_cases/bash/bashbox-xargs.test.sh new file mode 100644 index 000000000..a6c6ca98c --- /dev/null +++ b/crates/bashkit/tests/spec_cases/bash/bashbox-xargs.test.sh @@ -0,0 +1,344 @@ +# BashBox xargs cases +# Imported from github.com/shipfastlabs/bashbox tests/ (MIT, Copyright (c) Pushpak Chhajed; see NOTICE). +# Expected stdout was recorded from GNU bash and re-verified against host bash before import. + +### bashbox_xargs_defaults_to_echo +# defaults to echo +printf 'a b\n c' | xargs +### expect +a b c +### end + +### bashbox_xargs_appends_items_to_the_command +# appends items to the command +echo a b | xargs echo X +### expect +X a b +### end + +### bashbox_xargs_n_limits_items_per_run +# -n limits items per run +echo a b c | xargs -n 2; echo a b | xargs -n1 echo - +### expect +a b +c +- a +- b +### end + +### bashbox_xargs_options_after_the_command_belong_to_it +# options after the command belong to it +echo a b | xargs -n1 echo -n; echo +### expect +ab +### end + +### bashbox_xargs_i_runs_once_per_line_keeping_trailing_blanks +# -I runs once per line, keeping trailing blanks +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'one\n\n two \n' | xargs -I {} echo '<{}>' {} +### expect + one + two +### end + +### bashbox_xargs_i_with_an_attached_placeholder +# -I with an attached placeholder +echo x | xargs -I% echo [%] +### expect +[x] +### end + +### bashbox_xargs_runs_once_on_empty_input +# runs once on empty input +printf '' | xargs echo hi +### expect +hi +### end + +### bashbox_xargs_r_skips_empty_input +# -r skips empty input +printf '' | xargs -r echo hi +### expect +### end + +### bashbox_xargs_quotes_and_backslashes_group_words +# quotes and backslashes group words +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '%s\n' '"a b" '\''c d'\'' e\\ f g\\\\h' 'i\\' 'j' | xargs -n1 echo +### expect +a b +c d +e\ +f +g\\h +i\ +j +### end + +### bashbox_xargs_an_empty_quoted_word_is_kept_but_a_final_one_is_dropped +# an empty quoted word is kept but a final one is dropped +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf '"" a\nb ""' | xargs -n1 echo -; printf "c '" | xargs echo +### expect +- +- a +- b +c +### end + +### bashbox_xargs_a_backslash_escapes_a_newline +# a backslash escapes a newline +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\\\nb\n' | xargs -n1 echo; printf 'c\\' | xargs echo +### expect +a +b +c +### end + +### bashbox_xargs_a_nul_ends_an_argument_with_a_warning +# a NUL ends an argument, with a warning +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\0b c\0d\n' | xargs echo +### expect +a c +### end + +### bashbox_xargs_0_splits_at_nuls +# -0 splits at NULs +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b\0\0c\0' | xargs -0 -n1 echo - +### expect +- a b +- +- c +### end + +### bashbox_xargs_d_takes_a_character_or_an_escape +# -d takes a character or an escape +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a,b,,c' | xargs -d, echo; printf 'a\tb\n' | xargs -d '\t' echo; printf 'aXb' | xargs -d '\x58' echo; printf 'aXb' | xargs --delimiter='\130' echo; printf 'a\ab' | xargs -d '\a' echo +### expect +a b c +a b + +a b +a b +a b +### end + +### bashbox_xargs_d_numbers_are_read_like_strtoul +# -d numbers are read like strtoul +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'aAb' | xargs -d '\x 41' echo; printf 'aAb' | xargs -d '\x+0x41' echo; printf 'a\0b' | xargs -d '\x' echo; printf 'a\0b' | xargs -d '\x-0' echo +### expect +a b +a b +a b +a b +### end + +### bashbox_xargs_d_items_keep_blanks_and_quotes +# -d items keep blanks and quotes +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf "a 'b\nc\n" | xargs -d '\n' -n1 echo +### expect +a 'b +c +### end + +### bashbox_xargs_e_stops_at_the_end_of_file_word +# -E stops at the end-of-file word +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b\nSTOP\nc\n' | xargs -E STOP echo; printf 'a STOP b\n' | xargs -eSTOP echo; printf 'STOP\nc\n' | xargs --eof=STOP echo x; printf 'a STOP' | xargs -E STOP; printf 'STOP' | xargs -E STOP echo y +### expect +a b +a +x +a STOP +y +### end + +### bashbox_xargs_e_on_a_line_ending +# -E on a line ending +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a STOP\nb\n' | xargs -E STOP -L1 echo +### expect +a +### end + +### bashbox_xargs_a_bare_e_turns_e_off +# a bare -e turns -E off +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a x b | xargs -E x -e echo; echo a x b | xargs -E x --eof echo +### expect +a x b +a x b +### end + +### bashbox_xargs_e_has_no_effect_with_0_or_d +# -E has no effect with -0 or -d +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\0x\0b' | xargs -E x -0 echo +### expect +a x b +### end + +### bashbox_xargs_l_runs_per_lines +# -L runs per lines +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\nc\nd\ne\n' | xargs -L2 echo +### expect +a b +c d +e +### end + +### bashbox_xargs_l_continues_a_line_ending_in_a_blank +# -L continues a line ending in a blank +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b \nc\nd\\ \ne\n' | xargs -L1 echo +### expect +a b c +d e +### end + +### bashbox_xargs_l_defaults_to_one_line +# -l defaults to one line +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\nc\n' | xargs -l echo; printf 'a\nb\nc\n' | xargs -l2 echo; printf 'a\nb\n' | xargs --max-lines echo +### expect +a +b +c +a b +c +a +b +### end + +### bashbox_xargs_a_bare_optional_option_at_the_end_of_a_bundle +# a bare optional option at the end of a bundle +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a x b | xargs -E x -tl echo; echo y | xargs -ti echo {}; echo z | xargs -it echo {} +### expect +a +y +{} +### end + +### bashbox_xargs_l_n_and_i_exclude_each_other +# -L, -n and -I exclude each other +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\nc\n' | xargs -n2 -L1 echo; printf 'a\nb\nc\n' | xargs -L1 -n2 echo; printf 'a\nb\n' | xargs -I{} -l echo {} +### expect +a +b +c +a b +c +{} a +{} b +### end + +### bashbox_xargs_i_excludes_n_and_l +# -I excludes -n and -L +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\n' | xargs -L1 -I{} echo {}; printf 'a\nb\n' | xargs -n2 -I{} echo {}; printf 'a\nb\n' | xargs -I{} -n2 echo {} +### expect +a +b +a +b +{} a b +### end + +### bashbox_xargs_n1_after_i_is_ignored +# -n1 after -I is ignored +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b\nc\n' | xargs -I{} -n1 echo [{}] +### expect +[a b] +[c] +### end + +### bashbox_xargs_i_defaults_to +# -i defaults to {} +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\n' | xargs -i echo {}; echo c | xargs --replace echo {}; echo d | xargs -iX echo X +### expect +a +b +c +d +### end + +### bashbox_xargs_numbers_may_have_blanks_and_a_sign +# numbers may have blanks and a sign +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +echo a b c | xargs -n ' +2' echo; echo d | xargs -P 2 echo +### expect +a b +c +d +### end + +### bashbox_xargs_s_limits_the_command_length +# -s limits the command length +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\nc\n' | xargs -s 9 echo +### expect +a b +c +### end + +### bashbox_xargs_x_alone_still_splits +# -x alone still splits +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b c d\n' | xargs -x -s 9 echo +### expect +a b +c d +### end + +### bashbox_xargs_i_size_limits +# -I size limits +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'abc\n' | xargs -I{} -s 8 echo {} {}; printf 'abcde\n' | xargs -I{} -s 6 echo x{}; printf 'abcdef\n' | xargs -I{} -s 6 echo x{}; printf 'a\n' | xargs -I{} -s 3 echo {}; printf '' | xargs -I{} -s 3 echo {} +### expect +### end + +### bashbox_xargs_i_with_0 +# -I with -0 +printf 'a b\0c\0' | xargs -0 -I{} echo [{}] +### expect +[a b] +[c] +### end + +### bashbox_xargs_a_reads_standard_input +# -a - reads standard input +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a\nb\n' | xargs -a - echo +### expect +a b +### end + +### bashbox_xargs_a_with_a_directory_reads_nothing +# -a with a directory reads nothing +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +mkdir d; xargs -a d echo x +### expect +x +### end + +### bashbox_xargs_t_prints_each_command +# -t prints each command +### skip: TODO bashbox corpus gap, bashkit output differs from real bash +printf 'a b\nc\n' | xargs -t -n2 echo; printf "it's\ta b\n" | xargs -d '\n' --verbose +### expect +a b +c +it's a b +### end diff --git a/knowledge/operations/testing.md b/knowledge/operations/testing.md index c27e6ded1..c9b7bc915 100644 --- a/knowledge/operations/testing.md +++ b/knowledge/operations/testing.md @@ -295,6 +295,26 @@ Quarterly import process: 4. CI runs the same feature-complete, network-free lane. Schema, provenance, unique IDs, classifications, and limitation references are test-enforced. +## Imported BashBox Corpus + +`spec_cases/bash/bashbox-*.test.sh` holds bash-parity cases copied from the +test suite of [BashBox](https://github.com/shipfastlabs/bashbox) (MIT, PHP port +of just-bash; attribution in `NOTICE`). One file per BashBox test file. +Imported 2026-10-07: 1,753 (script, stdout) pairs extracted, kept only those +whose recorded stdout matched host bash 5.2 under `LANG=C.UTF-8`, and whose +expectation is representable in the spec format (1,044 cases). + +- 624 pass in Bashkit and run in both the spec suite and the bash comparison gate. +- 420 are `### skip: TODO bashbox corpus gap` — Bashkit's stdout or exit status + differs from real bash. These are bugs, not intentional divergences: fixing + one means deleting its `skip` line (the comparison gate then guards it). + Clusters: `declare`/`local`/attributes, `sort` and `xargs` flags, arithmetic on + arrays, `declare -f`/`type` printing, named fds, ERR trap, `printf`, `tr`. + +Do not re-import over existing files; fix cases in place. If an intentional +divergence is found, switch the case to `### bash_diff` with a canonical `L-*` +row in [Known Limitations](limitations.md). + ## SQLite CLI Differential Tests CSV comparisons explicitly set the host CLI row separator to LF. SQLite