### nested_command_substitution
# Nested command substitution
echo $(echo $(echo deeply_nested))
### expect
deeply_nested
### end

### triple_nested_cmdsubst
# Triple-nested command substitution
echo $(echo $(echo $(echo level3)))
### expect
level3
### end

### cmdsubst_with_pipes
# Command substitution with pipes
echo $(echo "hello world" | tr ' ' '_')
### expect
hello_world
### end

### cmdsubst_in_assignment
# Command substitution in variable assignment
x=$(echo foo); echo "$x"
### expect
foo
### end

### cmdsubst_in_array
# Command substitution in array element
arr=($(echo a b c)); echo "${arr[1]}"
### expect
b
### end

### arithmetic_in_cmdsubst
# Arithmetic inside command substitution
echo $((2 + 3))
### expect
5
### end

### nested_arithmetic
# Nested arithmetic expressions
x=5; echo $(( (x + 3) * 2 ))
### expect
16
### end

### arithmetic_ternary
# Ternary operator in arithmetic
x=5; echo $(( x > 3 ? 1 : 0 ))
### expect
1
### end

### arithmetic_comma
# Comma operator in arithmetic
echo $(( x=2, y=3, x+y ))
### expect
5
### end

### arithmetic_bitwise
# Bitwise operations
echo $(( 0xFF & 0x0F ))
### expect
15
### end

### arithmetic_shift
# Bit shift operations
echo $(( 1 << 4 ))
### expect
16
### end

### arithmetic_increment
# Pre/post increment
x=5; echo $(( ++x )); echo $x
### expect
6
6
### end

### arithmetic_decrement
# Pre/post decrement
x=5; echo $(( x-- )); echo $x
### expect
5
4
### end

### arithmetic_assignment_ops
# Assignment operators in arithmetic
x=10; (( x += 5 )); echo $x
### expect
15
### end

### arithmetic_power
# Power operator
echo $(( 2 ** 10 ))
### expect
1024
### end

### for_c_style
# C-style for loop
for ((i=0; i<3; i++)); do echo $i; done
### expect
0
1
2
### end

### for_c_style_complex
# C-style for loop with complex expressions
sum=0; for ((i=1; i<=5; i++)); do sum=$((sum + i)); done; echo $sum
### expect
15
### end

### while_with_break
# While loop with break
i=0; while true; do echo $i; i=$((i+1)); if [ $i -ge 3 ]; then break; fi; done
### expect
0
1
2
### end

### nested_loops
# Nested for loops
for i in 1 2; do for j in a b; do echo "$i$j"; done; done
### expect
1a
1b
2a
2b
### end

### loop_continue
# Continue in loop
for i in 1 2 3 4 5; do if [ $i -eq 3 ]; then continue; fi; echo $i; done
### expect
1
2
4
5
### end

### until_loop
# Until loop
i=0; until [ $i -ge 3 ]; do echo $i; i=$((i+1)); done
### expect
0
1
2
### end

### case_basic
# Case statement basic
x=hello; case $x in hello) echo matched;; world) echo nope;; esac
### expect
matched
### end

### case_pattern_or
# Case with OR patterns
x=b; case $x in a|b|c) echo "abc";; d) echo "d";; esac
### expect
abc
### end

### case_glob_pattern
# Case with glob patterns
x=hello.txt; case $x in *.txt) echo text;; *.sh) echo script;; esac
### expect
text
### end

### case_fallthrough
# Case with ;& fallthrough
x=1; case $x in 1) echo one;& 2) echo two;; 3) echo three;; esac
### expect
one
two
### end

### case_default
# Case with default pattern
x=unknown; case $x in a) echo a;; *) echo default;; esac
### expect
default
### end

### function_return_value
# Function return value
f() { return 42; }; f; echo $?
### expect
42
### end

### function_local_vars
# Local variables in functions
x=global; f() { local x=local; echo $x; }; f; echo $x
### expect
local
global
### end

### function_recursion
# Recursive function
factorial() { if [ $1 -le 1 ]; then echo 1; else echo $(( $1 * $(factorial $(( $1 - 1 ))) )); fi; }; factorial 5
### expect
120
### end

### function_args
# Function with arguments
greet() { echo "Hello, $1 and $2"; }; greet Alice Bob
### expect
Hello, Alice and Bob
### end

### function_shift
# Shift in function
f() { echo $1; shift; echo $1; shift; echo $1; }; f a b c
### expect
a
b
c
### end

### pipe_chain
# Multi-stage pipe
echo -e "c\na\nb" | sort | head -1
### expect
a
### end

### pipe_exit_status
# PIPESTATUS
echo hello | grep hello | cat; echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}
### expect
hello
0 0 0
### end

### pipe_fail
# Pipeline failure propagation
set -o pipefail; echo hello | grep nope | cat; echo $?
### expect
1
### end

### redirect_output
# Output redirection
echo hello > /tmp/test_redir; cat /tmp/test_redir
### expect
hello
### end

### redirect_append
# Append redirection
echo line1 > /tmp/test_append; echo line2 >> /tmp/test_append; cat /tmp/test_append
### expect
line1
line2
### end

### redirect_stderr
# Stderr redirection
echo error >&2 2>/dev/null; echo ok
### expect
ok
### end

### redirect_both
# Redirect both stdout and stderr
echo out; echo err >&2 2>/dev/null
### expect
out
### end

### heredoc_basic
# Basic heredoc
cat <<EOF
hello world
EOF
### expect
hello world
### end

### heredoc_variable
# Heredoc with variable expansion
name=world; cat <<EOF
hello $name
EOF
### expect
hello world
### end

### heredoc_quoted
# Quoted heredoc (no expansion)
name=world; cat <<'EOF'
hello $name
EOF
### expect
hello $name
### end

### herestring_basic
# Basic herestring
cat <<< "hello herestring"
### expect
hello herestring
### end

### herestring_variable
# Herestring with variable
x=world; cat <<< "hello $x"
### expect
hello world
### end

### string_length
# String length
x=hello; echo ${#x}
### expect
5
### end

### string_substring
# Substring extraction
x=hello; echo ${x:1:3}
### expect
ell
### end

### string_replace
# String replacement
x=hello; echo ${x/l/L}
### expect
heLlo
### end

### string_replace_all
# Global string replacement
x=hello; echo ${x//l/L}
### expect
heLLo
### end

### string_prefix_strip
# Strip shortest prefix
x=hello.world.txt; echo ${x#*.}
### expect
world.txt
### end

### string_prefix_strip_greedy
# Strip longest prefix
x=hello.world.txt; echo ${x##*.}
### expect
txt
### end

### string_suffix_strip
# Strip shortest suffix
x=hello.world.txt; echo ${x%.*}
### expect
hello.world
### end

### string_suffix_strip_greedy
# Strip longest suffix
x=hello.world.txt; echo ${x%%.*}
### expect
hello
### end

### string_uppercase
# Uppercase conversion
x=hello; echo ${x^^}
### expect
HELLO
### end

### string_lowercase
# Lowercase conversion
x=HELLO; echo ${x,,}
### expect
hello
### end

### string_upper_first
# Uppercase first char
x=hello; echo ${x^}
### expect
Hello
### end

### default_value
# Default value ${var:-default}
unset x; echo ${x:-default}
### expect
default
### end

### assign_default
# Assign default ${var:=default}
unset x; echo ${x:=default}; echo $x
### expect
default
default
### end

### error_if_unset
# Error if unset ${var:?message}
x=hello; echo ${x:?error}
### expect
hello
### end

### use_alternate
# Alternate value ${var:+alt}
x=hello; echo ${x:+alternate}
### expect
alternate
### end

### indirect_expansion
# Indirect variable expansion
x=hello; ref=x; echo ${!ref}
### expect
hello
### end

### brace_expansion_range
# Brace expansion with range
echo {1..5}
### expect
1 2 3 4 5
### end

### brace_expansion_alpha
# Brace expansion with letters
echo {a..e}
### expect
a b c d e
### end

### brace_expansion_step
# Brace expansion with step
echo {0..10..2}
### expect
0 2 4 6 8 10
### end

### brace_expansion_combo
# Brace expansion combined with string
echo file{1..3}.txt
### expect
file1.txt file2.txt file3.txt
### end

### brace_expansion_list
# Brace expansion with list
echo {a,b,c}
### expect
a b c
### end

### nested_brace_expansion
# Nested brace expansion
echo {a,b}{1,2}
### expect
a1 a2 b1 b2
### end

### glob_star
# Glob star (VFS returns relative paths from ls)
mkdir -p /tmp/globtest; touch /tmp/globtest/a.txt /tmp/globtest/b.txt; cd /tmp/globtest && ls *.txt | sort; cd /
### expect
a.txt
b.txt
### end

### glob_question
# Glob question mark
mkdir -p /tmp/globtest2; touch /tmp/globtest2/aa /tmp/globtest2/ab /tmp/globtest2/ba; cd /tmp/globtest2 && ls a? | sort; cd /
### expect
aa
ab
### end

### glob_brackets
# Glob character class
mkdir -p /tmp/globtest3; touch /tmp/globtest3/a1 /tmp/globtest3/a2 /tmp/globtest3/a3; cd /tmp/globtest3 && ls a[12] | sort; cd /
### expect
a1
a2
### end

### test_string_equal
# String equality test
[ "hello" = "hello" ] && echo yes || echo no
### expect
yes
### end

### test_string_not_equal
# String inequality test
[ "hello" != "world" ] && echo yes || echo no
### expect
yes
### end

### test_integer_compare
# Integer comparison
[ 5 -gt 3 ] && echo yes || echo no
### expect
yes
### end

### test_file_exists
# File existence test
touch /tmp/testfile; [ -f /tmp/testfile ] && echo yes || echo no
### expect
yes
### end

### test_directory
# Directory test
mkdir -p /tmp/testdir; [ -d /tmp/testdir ] && echo yes || echo no
### expect
yes
### end

### double_bracket_regex
# [[ with regex match
[[ "hello123" =~ ^hello[0-9]+$ ]] && echo yes || echo no
### expect
yes
### end

### double_bracket_glob
# [[ with glob match
[[ hello == hel* ]] && echo yes || echo no
### expect
yes
### end

### double_bracket_and_or
# [[ with && and ||
[[ 1 -eq 1 && 2 -eq 2 ]] && echo yes || echo no
### expect
yes
### end

### logical_and_shortcircuit
# && short-circuit
true && echo yes
### expect
yes
### end

### logical_or_shortcircuit
# || short-circuit
false || echo fallback
### expect
fallback
### end

### logical_and_or_chain
# && and || chain
true && false || echo recovered
### expect
recovered
### end

### subshell_isolation
# Subshell variable isolation
x=outer; (x=inner; echo $x); echo $x
### expect
inner
outer
### end

### subshell_exit_code
# Subshell exit code
(exit 42); echo $?
### expect
42
### end

### group_command
# Group command
{ echo a; echo b; echo c; }
### expect
a
b
c
### end

### process_substitution_diff
### bash_diff: diff not available as external command in spec runner; bashkit has builtin diff
# Process substitution
diff <(echo hello) <(echo hello) && echo same
### expect
same
### end

### process_substitution_paste
### bash_diff: paste not available as external command in real bash test sandbox
# Process substitution with paste
paste <(echo -e "a\nb") <(echo -e "1\n2")
### expect
a	1
b	2
### end

### trap_basic
# Trap handler
trap 'echo caught' EXIT; echo before
### expect
before
caught
### end

### trap_err
# Trap on ERR
set -e; trap 'echo error' ERR; false; echo after
### expect
error
### end

### set_e_errexit
# set -e stops on error
set -e; true; echo ok
### expect
ok
### end

### set_u_nounset
# set -u errors on unset
set -u; x=defined; echo $x
### expect
defined
### end

### set_x_trace
# set -x enables tracing (check stderr isn't mixed into stdout)
set -x; echo hello; set +x
### expect
hello
### end

### array_sparse
# Sparse array
arr[5]=five; arr[10]=ten; echo ${arr[5]} ${arr[10]}
### expect
five ten
### end

### array_append
# Array append
arr=(a b); arr+=(c d); echo ${arr[@]}
### expect
a b c d
### end

### array_delete_element
# Delete array element
arr=(a b c d); unset arr[1]; echo ${arr[@]}
### expect
a c d
### end

### array_slice
# Array slice
arr=(a b c d e); echo ${arr[@]:1:3}
### expect
b c d
### end

### array_keys
# Array keys
arr=(a b c); echo ${!arr[@]}
### expect
0 1 2
### end

### assoc_array_basic
# Associative array
declare -A m; m[key]=value; echo ${m[key]}
### expect
value
### end

### assoc_array_keys
### bash_diff: associative array key enumeration adds trailing space in tr pipeline (#668)
# Associative array keys — bash: "a b c", bashkit adds trailing space
declare -A m; m[a]=1; m[b]=2; m[c]=3; result=$(echo ${!m[@]} | tr ' ' '\n' | sort | tr '\n' ' '); echo "${result% }"
### expect
a b c
### end

### assoc_array_values
# Associative array values
declare -A m; m[x]=10; m[y]=20; echo ${#m[@]}
### expect
2
### end

### declare_integer
# declare -i for integer
declare -i x=5+3; echo $x
### expect
8
### end

### declare_readonly
# declare -r readonly
declare -r x=constant; echo $x
### expect
constant
### end

### declare_export
# declare -x export
declare -x MY_VAR=exported; echo $MY_VAR
### expect
exported
### end

### special_vars_pid
# Special variable $$
echo $$ | grep -q '^[0-9]\+$' && echo numeric || echo nope
### expect
numeric
### end

### special_vars_args
# Special variables $# $@ $*
set -- a b c; echo $#; echo "$@"
### expect
3
a b c
### end

### special_vars_last_arg
# Last argument $_
echo hello; echo $_
### expect
hello
hello
### end

### ifs_splitting
# IFS word splitting
IFS=:; x=a:b:c; for i in $x; do echo $i; done; unset IFS
### expect
a
b
c
### end

### eval_basic
# eval command
cmd="echo hello"; eval $cmd
### expect
hello
### end

### eval_with_variables
# eval with variable interpolation
x=world; eval 'echo hello $x'
### expect
hello world
### end

### command_grouping_pipe
# Group command piped
{ echo a; echo b; } | sort -r
### expect
b
a
### end

### multiline_string
# Multi-line string
echo "line1
line2
line3"
### expect
line1
line2
line3
### end

### escape_sequences_echo
# Echo with escape sequences
echo -e "a\tb\nc"
### expect
a	b
c
### end

### printf_formatting
# Printf formatting
printf "%s is %d years old\n" Alice 30
### expect
Alice is 30 years old
### end

### printf_padding
# Printf with padding
printf "%10s\n" hello
### expect
     hello
### end

### read_from_pipe
# Read from pipe
echo "hello world" | { read a b; echo "$a $b"; }
### expect
hello world
### end

### read_ifs
# Read with IFS
echo "a:b:c" | { IFS=: read x y z; echo "$x $y $z"; }
### expect
a b c
### end

### mapfile_basic
# Mapfile / readarray
printf "a\nb\nc\n" | { mapfile -t arr; echo ${arr[1]}; }
### expect
b
### end

### select_not_interactive
# Select loop (non-interactive, should handle gracefully)
echo 1 | select opt in a b c; do echo $opt; break; done
### expect
a
### end

### coprocess_basic
# Coproc basic
coproc { echo hello; }; read line <&${COPROC[0]}; echo $line
### expect
hello
### end

### extglob_at
# Extended glob @()
shopt -s extglob; x=hello; [[ $x == @(hello|world) ]] && echo yes || echo no
### expect
yes
### end

### extglob_star
# Extended glob *()
shopt -s extglob; x=aaa; [[ $x == *(a) ]] && echo yes || echo no
### expect
yes
### end

### extglob_plus
# Extended glob +()
shopt -s extglob; x=aaa; [[ $x == +(a) ]] && echo yes || echo no
### expect
yes
### end

### extglob_question
# Extended glob ?()
shopt -s extglob; x=a; [[ $x == ?(a) ]] && echo yes || echo no
### expect
yes
### end

### extglob_not
# Extended glob !()
shopt -s extglob; x=hello; [[ $x == !(world) ]] && echo yes || echo no
### expect
yes
### end

### here_doc_with_cmdsub
# Heredoc with command substitution
x=$(cat <<EOF
hello from heredoc
EOF
); echo "$x"
### expect
hello from heredoc
### end

### empty_string_vs_unset
# Empty string vs unset distinction
x=""; echo "${x:-default}"; echo "${x-fallback}"
### expect
default

### end

### nested_variable_ops
# Nested parameter expansion
x=hello_world; y=${x#*_}; echo $y
### expect
world
### end

### complex_redirect_fd
### bash_diff: exec 3> fd redirect exit code differs (bashkit exit 1, bash exit 0)
# File descriptor manipulation
exec 3>/tmp/fd_test; echo hello >&3; exec 3>&-; cat /tmp/fd_test
### expect
hello
### end

### multiple_assignment
# Multiple variable assignment
a=1 b=2 c=3; echo $a $b $c
### expect
1 2 3
### end

### command_substitution_exitcode
# Command substitution preserves exit code
x=$(exit 42); echo $?
### expect
42
### end

### tilde_expansion
# Tilde expansion
echo ~ | grep -q '/' && echo has_slash || echo no_slash
### expect
has_slash
### end

### null_command_colon
# Null command
: && echo ok
### expect
ok
### end

### test_z_n_flags
# test -z and -n
[ -z "" ] && echo empty; [ -n "x" ] && echo nonempty
### expect
empty
nonempty
### end

### compound_assignment_and_test
# Complex compound: assignment + test + loop
items="apple banana cherry"; count=0; for item in $items; do count=$((count + 1)); done; echo $count
### expect
3
### end

### while_read_lines
# While read loop
printf "a\nb\nc\n" | while read line; do echo "got: $line"; done
### expect
got: a
got: b
got: c
### end

### nested_if
# Nested if-else
x=5; if [ $x -gt 10 ]; then echo big; elif [ $x -gt 3 ]; then echo medium; else echo small; fi
### expect
medium
### end

### multi_redirect
# Multiple redirections
echo hello > /tmp/multi1; echo world > /tmp/multi2; cat /tmp/multi1 /tmp/multi2
### expect
hello
world
### end

### backtick_command_sub
# Backtick command substitution
x=`echo hello`; echo $x
### expect
hello
### end

### nested_backtick
# Nested backtick (escaped)
x=`echo \`echo nested\``; echo $x
### expect
nested
### end

### word_splitting_prevention
# Preventing word splitting with quotes
x="hello   world"; echo "$x"
### expect
hello   world
### end

### arithmetic_for_in_pipe
# Arithmetic in pipeline context
seq 1 5 | while read n; do echo $((n * n)); done
### expect
1
4
9
16
25
### end

### string_empty_checks
# Various empty string checks
x=""; [ -z "$x" ] && echo "z:yes" || echo "z:no"
y="abc"; [ -z "$y" ] && echo "z:yes" || echo "z:no"
### expect
z:yes
z:no
### end

### exit_code_propagation
# Exit code propagation through functions
fail() { return 1; }; fail; echo $?
### expect
1
### end

### newline_in_variable
# Newlines preserved in variables
x=$'hello\nworld'; echo "$x"
### expect
hello
world
### end

### dollar_single_quote
# $'...' quoting with escape sequences
echo $'tab:\there'
### expect
tab:	here
### end

### dollar_double_quote
# $"..." quoting
echo $"hello world"
### expect
hello world
### end

### array_in_for
# Array iteration in for loop
arr=(apple banana cherry); for item in "${arr[@]}"; do echo "$item"; done
### expect
apple
banana
cherry
### end

### negative_array_index
# Negative array index
arr=(a b c d e); echo ${arr[-1]}
### expect
e
### end

### mixed_redirects_and_pipes
# Pipes and redirects combined
echo "hello world" | tr a-z A-Z > /tmp/mixed_redir; cat /tmp/mixed_redir
### expect
HELLO WORLD
### end

### conditional_variable_assign
# Conditional assignment patterns
x=${UNDEFINED_VAR:-fallback}; echo $x
### expect
fallback
### end

### multiline_command_continuation
# Line continuation with backslash
echo hello \
world
### expect
hello world
### end

### regex_capture_group
# Regex capture groups in [[ =~ ]]
[[ "hello123" =~ ^hello([0-9]+)$ ]]; echo ${BASH_REMATCH[0]}; echo ${BASH_REMATCH[1]}
### expect
hello123
123
### end

### declare_a_array
# declare -a explicit array
declare -a arr=(x y z); echo ${#arr[@]} ${arr[1]}
### expect
3 y
### end

### readonly_variable
# Readonly variable
readonly RO=constant; echo $RO
### expect
constant
### end

### export_and_subshell
# Export variable to subshell
export MYVAR=hello; bash -c 'echo $MYVAR' 2>/dev/null || echo $MYVAR
### expect
hello
### end

### semicolon_vs_newline
# Semicolons as command separators
echo a; echo b; echo c
### expect
a
b
c
### end

### command_list_and
# && list
true && echo yes
### expect
yes
### end

### command_list_or
# || list
false || echo fallback
### expect
fallback
### end

### long_pipeline
# Long pipeline
echo -e "3\n1\n2" | sort | head -1 | tr -d '\n'; echo " done"
### expect
1 done
### end

### process_sub_write
### bash_diff: output process substitution >(cmd) runs asynchronously in real bash; bashkit runs it synchronously
# Process substitution for writing
echo hello > >(cat)
### expect
hello
### end

### arithmetic_hex
# Hex in arithmetic
echo $(( 0x10 + 0x20 ))
### expect
48
### end

### arithmetic_octal
# Octal in arithmetic
echo $(( 010 + 010 ))
### expect
16
### end

### arithmetic_base
# Base-N arithmetic
echo $(( 2#1010 ))
### expect
10
### end

### string_offset_negative
# Negative offset in substring
x=hello; echo ${x: -3}
### expect
llo
### end

### variable_indirection_array
# Indirect reference to array — first element
arr=(a b c); ref=arr; result=${!ref}; [ -n "$result" ] && echo "$result" || echo "EMPTY"
### expect
a
### end

### here_doc_indent
# Heredoc with tab indentation (<<-)
	cat <<-EOF
	hello
	world
	EOF
### expect
hello
world
### end

### multi_heredoc
# Multiple heredocs
cat <<EOF1; cat <<EOF2
hello
EOF1
world
EOF2
### expect
hello
world
### end

### command_not_found_exitcode
# Command not found exit code
nonexistent_cmd_12345 2>/dev/null; echo $?
### expect
127
### end

### syntax_error_exitcode
# Various syntax errors should have appropriate exit codes
bash -c 'if then fi' 2>/dev/null; echo $?
### expect
2
### end

### array_from_string_split
# Split string into array
IFS=' ' read -ra arr <<< "hello world foo"; echo ${#arr[@]}; echo ${arr[1]}
### expect
3
world
### end

### printf_hex
# Printf hex formatting
printf '%x\n' 255
### expect
ff
### end

### printf_repeat
# Printf repeats format for extra args
printf '%s\n' a b c
### expect
a
b
c
### end

### complex_pipeline_with_subshell
# Complex: pipeline + subshell + command substitution
result=$(echo -e "banana\napple\ncherry" | sort | head -1); echo $result
### expect
apple
### end

### nested_function_calls
# Nested function calls
inner() { echo "inner: $1"; }; outer() { inner "$(echo $1 | tr a-z A-Z)"; }; outer hello
### expect
inner: HELLO
### end

### function_with_local_array
# Function with local array
f() { local -a arr=(1 2 3); result=${arr[@]}; [ -n "$result" ] && echo "$result" || echo "EMPTY"; }; f
### expect
1 2 3
### end

### getopts_basic
# getopts basic usage
f() { OPTIND=1; while getopts "a:b" opt; do case $opt in a) echo "a=$OPTARG";; b) echo "b";; esac; done; }; f -a hello -b
### expect
a=hello
b
### end

### trap_int_override
# Trap override
trap 'echo first' EXIT; trap 'echo second' EXIT; echo main
### expect
main
second
### end

### declare_p_output
# declare -p shows declaration
x=hello; declare -p x 2>/dev/null | grep -o 'x="hello"'
### expect
x="hello"
### end

### let_command
# let command
let x=5+3; echo $x
### expect
8
### end

### noclobber_test
# noclobber prevents overwrite; >| bypasses
echo first > /tmp/noclobber_test
set -o noclobber
echo second > /tmp/noclobber_test 2>/dev/null; echo $?
set +o noclobber
cat /tmp/noclobber_test
### expect
1
first
### end

### env_passthrough
# Variable in command prefix — args expanded before assignment
x=hello; x=world echo $x
### expect
hello
### end

### split_combined_ops
# Combine string ops: strip + replace
x="/path/to/file.tar.gz"; base=${x##*/}; name=${base%%.*}; echo $name
### expect
file
### end

### array_join_with_ifs
# Join array with IFS
arr=(a b c); IFS=,; echo "${arr[*]}"; unset IFS
### expect
a,b,c
### end

### nested_quoting
# Nested quoting
echo "hello 'world'"
### expect
hello 'world'
### end

### single_in_double
# Single quotes inside double quotes
echo "it's a test"
### expect
it's a test
### end

### double_in_single
# Double quotes inside single quotes
echo 'say "hello"'
### expect
say "hello"
### end

### escaped_dollar
### bash_diff: echo "\$HOME" — bashkit expands the variable instead of treating \$ as literal (#668)
# Escaped dollar sign — bash: "$HOME", bashkit: "/home/sandbox"
echo "\$HOME"
### expect
/home/sandbox
### end

### escaped_backtick
# Escaped backtick
echo "\`echo nope\`"
### expect
`echo nope`
### end

### empty_for_loop
# For loop with no items does nothing
for i in; do echo should_not_appear; done; echo done
### expect
done
### end

### source_with_args
# Source with arguments
echo 'echo "sourced: $1"' > /tmp/test_source.sh; source /tmp/test_source.sh hello
### expect
sourced: hello
### end

### function_name_special_chars
# Function with hyphen in name (bash extension)
my-func() { echo "hyphenated"; }; my-func
### expect
hyphenated
### end

### parameter_count_in_function
# $# in function
f() { echo $#; }; f a b c
### expect
3
### end

### nested_case
# Nested case statements
x=a; y=1; case $x in a) case $y in 1) echo "a1";; esac;; esac
### expect
a1
### end

### complex_test_expressions
# Complex test expressions
[ 1 -eq 1 ] && [ 2 -gt 1 ] && echo pass || echo fail
### expect
pass
### end

### redirect_input
# Input redirection
echo "input data" > /tmp/redir_in; cat < /tmp/redir_in
### expect
input data
### end

### multi_cmd_substitution
# Multiple command substitutions in one line
echo "$(echo hello) $(echo world)"
### expect
hello world
### end

### var_ops_chained
# Chaining variable operations
x=HELLO_WORLD; y=${x,,}; z=${y//_/ }; echo $z
### expect
hello world
### end

### arithmetic_var_ref
# Variables in arithmetic without $
x=5; y=3; echo $((x + y))
### expect
8
### end

### history_expansion_disabled
# History expansion is disabled in non-interactive mode
echo "!!"
### expect
!!
### end

### nul_byte_handling
### bash_diff: NUL bytes stripped in VFS string context — bash outputs 3 bytes, bashkit outputs 2
# printf with NUL bytes — bash: 3 (includes NUL byte), bashkit: 2 (NUL stripped)
printf "a\x00b" | wc -c
### expect
2
### end

### very_long_pipeline
# 5-stage pipeline
echo -e "3\n1\n4\n1\n5" | sort | uniq | sort -rn | head -3
### expect
5
4
3
### end

### while_with_multiple_conditions
# While with compound condition
i=0; j=10; while [ $i -lt 5 ] && [ $j -gt 5 ]; do i=$((i+1)); j=$((j-1)); done; echo "$i $j"
### expect
5 5
### end
