### cond_string_equal
# [[ string comparison ==
[[ "hello" == "hello" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_string_not_equal
# [[ string !=
[[ "hello" != "world" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_string_less
# [[ string <
[[ "abc" < "def" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_string_greater
# [[ string >
[[ "def" > "abc" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_negation
# [[ ! negation
[[ ! "hello" == "world" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_and
# [[ && logical and
[[ "a" == "a" && "b" == "b" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_or
# [[ || logical or
[[ "a" == "b" || "b" == "b" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_z_empty
# [[ -z empty string
[[ -z "" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_n_nonempty
# [[ -n non-empty string
[[ -n "hello" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_numeric_eq
# [[ numeric -eq
[[ 42 -eq 42 ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_numeric_lt
# [[ numeric -lt
[[ 5 -lt 10 ]] && echo "yes" || echo "no"
### expect
yes
### end

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

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

### cond_regex_capture
# [[ =~ with BASH_REMATCH capture groups
[[ "hello-world" =~ ^([a-z]+)-([a-z]+)$ ]] && echo "${BASH_REMATCH[1]} ${BASH_REMATCH[2]}"
### expect
hello world
### end

### cond_regex_rematch_full
# [[ =~ BASH_REMATCH[0] is full match
[[ "abc123" =~ [0-9]+ ]] && echo "${BASH_REMATCH[0]}"
### expect
123
### end

### cond_variable_expansion
# [[ with variable expansion
VAR="hello"
[[ "$VAR" == "hello" ]] && echo "yes" || echo "no"
### expect
yes
### end

### cond_exit_code_false
# [[ returns exit code 1 on false
[[ "a" == "b" ]]
echo $?
### expect
1
### end

### cond_glob_star
# [[ == ]] with * glob pattern
[[ "hello.txt" == *.txt ]] && echo match || echo no
### expect
match
### end

### cond_glob_star_no_match
# [[ == ]] glob * doesn't match wrong extension
[[ "hello.txt" == *.log ]] && echo match || echo no
### expect
no
### end

### cond_glob_question
# [[ == ]] with ? single-char glob
[[ "abc" == ?b? ]] && echo match || echo no
### expect
match
### end

### cond_glob_prefix
# [[ == ]] with prefix glob
[[ "hello_world" == hello* ]] && echo match || echo no
### expect
match
### end

### cond_glob_suffix
# [[ == ]] with suffix glob
[[ "test_file" == *_file ]] && echo match || echo no
### expect
match
### end

### cond_glob_not_equal
# [[ != ]] with glob pattern
[[ "hello.txt" != *.log ]] && echo diff || echo same
### expect
diff
### end

### cond_or_and_precedence
# && has higher precedence than || in [[: [[ true || false && false ]] => true
[[ -n "a" || -z "b" && -z "c" ]] && echo "correct" || echo "wrong"
### expect
correct
### end

### cond_or_and_precedence_reverse
# && binds tighter: [[ false && false || true ]] => true
[[ -z "a" && -z "b" || -n "c" ]] && echo "correct" || echo "wrong"
### expect
correct
### end


### cond_parenthesized_or_outer_and_false
# Parenthesized || must not be split before the outer &&.
a=""
b=""
c="1"
[[ ( "$a" || "$b" ) && "$c" ]] && echo wrong || echo correct
### expect
correct
### end

### cond_parenthesized_or_outer_and_true
# Parenthesized || evaluates first, then the outer &&.
a=""
b="1"
c="1"
[[ ( "$a" || "$b" ) && "$c" ]] && echo correct || echo wrong
### expect
correct
### end

### cond_exact_match_no_glob
# [[ == ]] exact match with no glob chars
[[ "hello" == "hello" ]] && echo yes || echo no
### expect
yes
### end

### cond_bracket_literal_match
# Issue #837: [] should be treated as literal when it's an invalid glob
x="[]"
if [[ "$x" == "[]" ]]; then echo match; else echo "no match"; fi
### expect
match
### end

### cond_single_bracket_literal
# Literal [ comparison
x="["
[[ "$x" == "[" ]] && echo match || echo "no match"
### expect
match
### end

### cond_valid_glob_bracket
# Valid glob [a] should still work as pattern
[[ "a" == [a] ]] && echo match || echo "no match"
### expect
match
### end

### cond_regex_hash_in_group
# `#` inside a regex group is part of the pattern, not a comment
l="## Title"
[[ $l =~ ^(#+)[[:space:]](.+)$ ]] && echo "${BASH_REMATCH[1]}|${BASH_REMATCH[2]}"
### expect
##|Title
### end

### cond_regex_hash_mid_word
[[ "a#b" =~ a#b ]] && echo yes
[[ "#" =~ ^#$ ]] && echo anchored
[[ x == x#y ]] || echo nomatch
### expect
yes
anchored
nomatch
### end

### cond_regex_unquoted_space_in_group
[[ "a b" =~ (a b) ]] && echo "${BASH_REMATCH[1]}"
### expect
a b
### end

### cond_regex_alternation
[[ "y" =~ x|y ]] && echo alt
### expect
alt
### end

### cond_regex_var_in_group
r="#"
[[ "#" =~ ($r) ]] && echo "${BASH_REMATCH[1]}"
### expect
#
### end

### cond_regex_quoting_is_literal
# Quoted text and backslash escapes match literally; a bare `$` is an anchor
[[ "a.b" =~ "a.b" ]] && echo q1
[[ "axb" =~ "a.b" ]] || echo q2
[[ ab =~ a\b ]] && echo q3
[[ axb =~ ^a\.b$ ]] || echo q4
[[ "a b" =~ ^a" "b$ ]] && echo q5
r=b; [[ ab =~ a$r$ ]] && echo q6
[[ x =~ (x$|y$) ]] && echo q7
[[ "x+" =~ x"+" ]] && echo q8
### expect
q1
q2
q3
q4
q5
q6
q7
q8
### end

### dbracket_grammar_errors_are_syntax_errors
# Operators must be bare words at parse time: status 2, nothing runs
for c in '[[ a $op a ]]' '[[ -z ]]' "[[ '(' x ]]" '[[ -f < ]]' '[[ ]]' '[[ && ]]' '[[ a == b c ]]' '[[ ( a ]]'; do
  op='=='; bash -c "$c; echo ran" 2>/dev/null; echo "$? $c"
done
### expect
2 [[ a $op a ]]
2 [[ -z ]]
2 [[ '(' x ]]
2 [[ -f < ]]
2 [[ ]]
2 [[ && ]]
2 [[ a == b c ]]
2 [[ ( a ]]
### end

### dbracket_quoted_operator_text_is_operand
[[ '!' == ! ]] && echo bang
[[ -n ! ]] && echo n
[[ x == x
&& y == y
]] && echo multiline
[[ 'foo()' == *\(\) ]] && echo m1
[[ 'foo()' == *'()' ]] && echo m2
### expect
bang
n
multiline
m1
m2
### end

### dbracket_after_assignment_is_a_command
FOO=bar [[ a == a ]] 2>/dev/null
echo $?
### expect
127
### end

### dbracket_redirect_catches_subst_stderr
[[ $(echo err >&2; echo x) == x ]] 2>/dev/null; echo $?
### expect
0
### end
