358 lines
10 KiB
YAML
358 lines
10 KiB
YAML
name: "Builtins: test"
|
|
cases:
|
|
- name: "test: = operator"
|
|
stdin: |
|
|
shopt -u nocasematch
|
|
test "ab" = "ab" && echo "ab = ab"
|
|
test "ab" = "AB" && echo "ab = AB"
|
|
test "ab" = "cd" && echo "ab = cd"
|
|
test "ab" = "a?" && echo "ab = a?"
|
|
|
|
shopt -s nocasematch
|
|
test "ab" = "ab" && echo "ab = ab"
|
|
test "ab" = "AB" && echo "ab = AB"
|
|
test "ab" = "cd" && echo "ab = cd"
|
|
test "ab" = "a?" && echo "ab = a?"
|
|
|
|
- name: "test: == operator"
|
|
stdin: |
|
|
shopt -u nocasematch
|
|
test "ab" == "ab" && echo "ab == ab"
|
|
test "ab" == "AB" && echo "ab == AB"
|
|
test "ab" == "cd" && echo "ab == cd"
|
|
test "ab" == "a?" && echo "ab == a?"
|
|
|
|
shopt -s nocasematch
|
|
test "ab" == "ab" && echo "ab == ab"
|
|
test "ab" == "AB" && echo "ab == AB"
|
|
test "ab" == "cd" && echo "ab == cd"
|
|
test "ab" == "a?" && echo "ab == a?"
|
|
|
|
- name: "test: files refer to same device and inode"
|
|
stdin: |
|
|
[ /bin/sh -ef /bin/sh ] && echo "-ef correctly identified device and inode numbers"
|
|
|
|
[ ! /etc/os-release -ef /bin/sh ] && echo "-ef correctly identified device and inode numbers that do not match"
|
|
|
|
- name: "test: file is newer"
|
|
stdin: |
|
|
touch -d "2 hours ago" bar
|
|
touch foo
|
|
|
|
[ foo -nt bar ] && echo "-nt correctly identified newer file"
|
|
[ foo -nt foo ] && echo "-nt incorrectly identified file as newer than itself"
|
|
[ foo -nt file_no_exists ] && echo "-nt correctly identified when file2 does not exist"
|
|
|
|
- name: "test: file is older"
|
|
stdin: |
|
|
touch -d "2 hours ago" foo
|
|
touch bar
|
|
|
|
[ foo -ot bar ] && echo "-ot correctly identified older file"
|
|
[ foo -ot foo ] && echo "-ot incorrectly identified file as older than itself"
|
|
[ file_no_exists -ot foo ] && echo "-ot correctly identified when file1 does not exist"
|
|
|
|
- name: "test: parens"
|
|
stdin: |
|
|
test \( "a" = "a" \) && echo "Parens work"
|
|
|
|
- name: "test: -- string"
|
|
stdin: |
|
|
test --
|
|
echo "Result(test): $?"
|
|
|
|
[ -- ]
|
|
echo "Result([): $?"
|
|
|
|
- name: "test: invalid operators"
|
|
ignore_stderr: true
|
|
stdin: |
|
|
test - -
|
|
echo "Result: $?"
|
|
|
|
# String operators
|
|
- name: "test: != operator"
|
|
stdin: |
|
|
test "ab" != "cd" && echo "ab != cd"
|
|
test "ab" != "ab" && echo "ab != ab"
|
|
test "" != "x" && echo "empty != x"
|
|
|
|
- name: "test: -z operator (zero length)"
|
|
stdin: |
|
|
test -z "" && echo "-z empty"
|
|
test -z "x" && echo "-z x"
|
|
unset VAR
|
|
test -z "$VAR" && echo "-z unset"
|
|
|
|
- name: "test: -n operator (non-zero length)"
|
|
stdin: |
|
|
test -n "x" && echo "-n x"
|
|
test -n "" && echo "-n empty"
|
|
VAR="hello"
|
|
test -n "$VAR" && echo "-n set"
|
|
|
|
- name: "test: < operator (string sort before)"
|
|
stdin: |
|
|
test "a" \< "b" && echo "a < b"
|
|
test "b" \< "a" && echo "b < a"
|
|
test "abc" \< "abd" && echo "abc < abd"
|
|
test "a" \< "a" && echo "a < a"
|
|
|
|
- name: "test: > operator (string sort after)"
|
|
stdin: |
|
|
test "b" \> "a" && echo "b > a"
|
|
test "a" \> "b" && echo "a > b"
|
|
test "abd" \> "abc" && echo "abd > abc"
|
|
test "a" \> "a" && echo "a > a"
|
|
|
|
# Arithmetic comparison operators
|
|
- name: "test: -eq operator"
|
|
stdin: |
|
|
test 5 -eq 5 && echo "5 -eq 5"
|
|
test 5 -eq 6 && echo "5 -eq 6"
|
|
test -1 -eq -1 && echo "-1 -eq -1"
|
|
test 0 -eq 0 && echo "0 -eq 0"
|
|
|
|
- name: "test: -ne operator"
|
|
stdin: |
|
|
test 5 -ne 6 && echo "5 -ne 6"
|
|
test 5 -ne 5 && echo "5 -ne 5"
|
|
test -1 -ne 1 && echo "-1 -ne 1"
|
|
|
|
- name: "test: -lt operator"
|
|
stdin: |
|
|
test 3 -lt 5 && echo "3 -lt 5"
|
|
test 5 -lt 3 && echo "5 -lt 3"
|
|
test 5 -lt 5 && echo "5 -lt 5"
|
|
test -2 -lt -1 && echo "-2 -lt -1"
|
|
|
|
- name: "test: -le operator"
|
|
stdin: |
|
|
test 3 -le 5 && echo "3 -le 5"
|
|
test 5 -le 5 && echo "5 -le 5"
|
|
test 6 -le 5 && echo "6 -le 5"
|
|
test -2 -le -2 && echo "-2 -le -2"
|
|
|
|
- name: "test: -gt operator"
|
|
stdin: |
|
|
test 5 -gt 3 && echo "5 -gt 3"
|
|
test 3 -gt 5 && echo "3 -gt 5"
|
|
test 5 -gt 5 && echo "5 -gt 5"
|
|
test -1 -gt -2 && echo "-1 -gt -2"
|
|
|
|
- name: "test: -ge operator"
|
|
stdin: |
|
|
test 5 -ge 3 && echo "5 -ge 3"
|
|
test 5 -ge 5 && echo "5 -ge 5"
|
|
test 3 -ge 5 && echo "3 -ge 5"
|
|
test -1 -ge -1 && echo "-1 -ge -1"
|
|
|
|
# File existence and type operators
|
|
- name: "test: -e operator (file exists)"
|
|
stdin: |
|
|
touch testfile
|
|
test -e testfile && echo "-e existing file"
|
|
test -e nonexistent && echo "-e nonexistent"
|
|
mkdir testdir
|
|
test -e testdir && echo "-e existing dir"
|
|
|
|
- name: "test: -a operator (file exists, deprecated)"
|
|
stdin: |
|
|
touch testfile
|
|
test -a testfile && echo "-a existing file"
|
|
test -a nonexistent && echo "-a nonexistent"
|
|
|
|
- name: "test: -f operator (regular file)"
|
|
stdin: |
|
|
touch testfile
|
|
test -f testfile && echo "-f regular file"
|
|
mkdir testdir
|
|
test -f testdir && echo "-f directory"
|
|
test -f nonexistent && echo "-f nonexistent"
|
|
|
|
- name: "test: -d operator (directory)"
|
|
stdin: |
|
|
mkdir testdir
|
|
test -d testdir && echo "-d directory"
|
|
touch testfile
|
|
test -d testfile && echo "-d regular file"
|
|
test -d nonexistent && echo "-d nonexistent"
|
|
|
|
- name: "test: -h and -L operators (symbolic link)"
|
|
stdin: |
|
|
touch target
|
|
ln -s target symlink
|
|
test -h symlink && echo "-h symlink"
|
|
test -L symlink && echo "-L symlink"
|
|
test -h target && echo "-h regular file"
|
|
test -L target && echo "-L regular file"
|
|
test -h nonexistent && echo "-h nonexistent"
|
|
|
|
- name: "test: -p operator (named pipe/FIFO)"
|
|
stdin: |
|
|
touch testfile
|
|
test -p testfile && echo "-p regular file"
|
|
test -p nonexistent && echo "-p nonexistent"
|
|
|
|
- name: "test: -S operator (socket)"
|
|
stdin: |
|
|
touch testfile
|
|
test -S testfile && echo "-S regular file"
|
|
test -S nonexistent && echo "-S nonexistent"
|
|
|
|
- name: "test: -b operator (block device)"
|
|
stdin: |
|
|
touch testfile
|
|
test -b testfile && echo "-b regular file"
|
|
test -b nonexistent && echo "-b nonexistent"
|
|
# Block devices exist in /dev but may vary by system
|
|
|
|
- name: "test: -c operator (character device)"
|
|
stdin: |
|
|
touch testfile
|
|
test -c testfile && echo "-c regular file"
|
|
test -c nonexistent && echo "-c nonexistent"
|
|
|
|
# File permission operators
|
|
- name: "test: -r operator (readable)"
|
|
stdin: |
|
|
touch testfile
|
|
test -r testfile && echo "-r readable"
|
|
test -r nonexistent && echo "-r nonexistent"
|
|
|
|
- name: "test: -w operator (writable)"
|
|
stdin: |
|
|
touch testfile
|
|
test -w testfile && echo "-w writable"
|
|
test -w nonexistent && echo "-w nonexistent"
|
|
|
|
- name: "test: -x operator (executable)"
|
|
stdin: |
|
|
touch testfile
|
|
test -x testfile && echo "-x executable"
|
|
|
|
- name: "test: -s operator (size greater than zero)"
|
|
stdin: |
|
|
echo "content" > nonempty
|
|
test -s nonempty && echo "-s nonempty"
|
|
touch empty
|
|
test -s empty && echo "-s empty"
|
|
test -s nonexistent && echo "-s nonexistent"
|
|
|
|
# Variable and option operators
|
|
- name: "test: -v operator (variable is set)"
|
|
stdin: |
|
|
VAR="hello"
|
|
test -v VAR && echo "-v set variable"
|
|
unset VAR
|
|
test -v VAR && echo "-v unset variable"
|
|
VAR=""
|
|
test -v VAR && echo "-v empty variable"
|
|
|
|
- name: "test: -R operator (nameref variable)"
|
|
stdin: |
|
|
VAR="value"
|
|
declare -n REF=VAR
|
|
test -R REF && echo "-R nameref"
|
|
test -R VAR && echo "-R regular var"
|
|
unset REF VAR
|
|
|
|
- name: "test: -o operator (shell option)"
|
|
stdin: |
|
|
set -e
|
|
test -o errexit && echo "-o errexit enabled"
|
|
set +e
|
|
test -o errexit && echo "-o errexit disabled"
|
|
test -o nonexistentoption && echo "-o nonexistent"
|
|
|
|
# Logical operators
|
|
- name: "test: ! operator (negation)"
|
|
stdin: |
|
|
test ! "a" = "b" && echo "! a=b"
|
|
test ! "a" = "a" && echo "! a=a"
|
|
test ! -e nonexistent && echo "! -e nonexistent"
|
|
test ! -e / && echo "! -e /"
|
|
|
|
- name: "test: -a operator (logical AND)"
|
|
stdin: |
|
|
test "a" = "a" -a "b" = "b" && echo "true -a true"
|
|
test "a" = "a" -a "b" = "c" && echo "true -a false"
|
|
test "a" = "b" -a "c" = "c" && echo "false -a true"
|
|
test "a" = "b" -a "c" = "d" && echo "false -a false"
|
|
|
|
- name: "test: -o operator (logical OR)"
|
|
stdin: |
|
|
test "a" = "a" -o "b" = "b" && echo "true -o true"
|
|
test "a" = "a" -o "b" = "c" && echo "true -o false"
|
|
test "a" = "b" -o "c" = "c" && echo "false -o true"
|
|
test "a" = "b" -o "c" = "d" && echo "false -o false"
|
|
|
|
- name: "test: complex logical expressions"
|
|
stdin: |
|
|
test \( "a" = "a" -o "b" = "c" \) -a "d" = "d" && echo "complex 1"
|
|
test ! \( "a" = "b" \) && echo "complex 2"
|
|
test "a" = "a" -a \( "b" = "b" -o "c" = "d" \) && echo "complex 3"
|
|
|
|
# Edge cases
|
|
- name: "test: single argument (non-empty string is true)"
|
|
stdin: |
|
|
test "hello" && echo "non-empty is true"
|
|
test "" && echo "empty is true"
|
|
test "0" && echo "zero string is true"
|
|
|
|
- name: "test: no arguments"
|
|
stdin: |
|
|
test
|
|
echo "no args: $?"
|
|
|
|
- name: "test: special characters in strings"
|
|
stdin: |
|
|
test "hello world" = "hello world" && echo "spaces match"
|
|
test "a b" = "a b" && echo "tabs match"
|
|
test 'a"b' = 'a"b' && echo "quotes match"
|
|
test "a'b" = "a'b" && echo "single quotes match"
|
|
|
|
- name: "test: arithmetic comparison with spaces/tabs in operand"
|
|
stdin: |
|
|
# Leading/trailing spaces
|
|
test 0 -eq ' 0'
|
|
echo "leading space: $?"
|
|
|
|
test 0 -eq '0 '
|
|
echo "trailing space: $?"
|
|
|
|
test 0 -eq ' 0 '
|
|
echo "both spaces: $?"
|
|
|
|
# Tabs
|
|
test 0 -eq ' 0'
|
|
echo "leading tab: $?"
|
|
|
|
test 0 -eq '0 '
|
|
echo "trailing tab: $?"
|
|
|
|
- name: "test: arithmetic comparison with newline in operand"
|
|
min_oracle_version: "5.3"
|
|
stdin: |
|
|
# Newline trimming seems to have changed in or around bash 5.3
|
|
test 0 -eq ' 0
|
|
'
|
|
echo "newline trailing: $?"
|
|
|
|
- name: "test: -t operator with whitespace in fd"
|
|
stdin: |
|
|
# -t operator should trim whitespace before parsing fd number
|
|
# These should all behave identically (false since not a terminal)
|
|
test -t 0
|
|
r1=$?
|
|
test -t ' 0'
|
|
r2=$?
|
|
test -t '0 '
|
|
r3=$?
|
|
test -t ' 0 '
|
|
r4=$?
|
|
|
|
# All should have the same result
|
|
[ $r1 -eq $r2 ] && [ $r2 -eq $r3 ] && [ $r3 -eq $r4 ] && echo "All -t results match"
|
|
|