| 1 | #!/bin/sh |
| 2 | # ===================================== |
| 3 | # POSIX Compliance File Test Operators Suite for shell |
| 4 | # ===================================== |
| 5 | # Tests test/[ builtin file and string operators per IEEE Std 1003.1-2017 |
| 6 | # Section: Shell Command Language - Conditional Expressions |
| 7 | |
| 8 | # Colors (POSIX-compliant way) |
| 9 | RED='\033[0;31m' |
| 10 | GREEN='\033[0;32m' |
| 11 | YELLOW='\033[1;33m' |
| 12 | BLUE='\033[0;34m' |
| 13 | NC='\033[0m' |
| 14 | |
| 15 | # Test identification |
| 16 | TEST_PREFIX="[posix-filetest]" |
| 17 | CURRENT_SECTION="" |
| 18 | TEST_NUM=0 |
| 19 | |
| 20 | PASSED=0 |
| 21 | FAILED=0 |
| 22 | SKIPPED=0 |
| 23 | FAILED_TESTS_LIST="" |
| 24 | |
| 25 | # Get script directory (POSIX way) |
| 26 | SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) |
| 27 | SHELL_BIN="${SHELL_BIN:?ERROR: SHELL_BIN must be set}" |
| 28 | |
| 29 | # Check if shell binary exists |
| 30 | if [ ! -x "$SHELL_BIN" ]; then |
| 31 | printf "${RED}ERROR${NC}: shell binary not found at $SHELL_BIN\n" |
| 32 | printf "Please set SHELL_BIN or set SHELL_BIN environment variable\n" |
| 33 | exit 1 |
| 34 | fi |
| 35 | |
| 36 | # Test result trackers |
| 37 | pass() { |
| 38 | TEST_NUM=$((TEST_NUM + 1)) |
| 39 | printf "${GREEN}✓ PASS${NC} ${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}: %s\n" "$1" |
| 40 | PASSED=$((PASSED + 1)) |
| 41 | } |
| 42 | |
| 43 | fail() { |
| 44 | TEST_NUM=$((TEST_NUM + 1)) |
| 45 | TEST_ID="${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}" |
| 46 | printf "${RED}✗ FAIL${NC} ${TEST_ID}: %s\n" "$1" |
| 47 | FAILED_TESTS_LIST="${FAILED_TESTS_LIST} ${TEST_ID}: $1\n" |
| 48 | if [ -n "$2" ]; then |
| 49 | printf " expected: %s\n" "$2" |
| 50 | fi |
| 51 | if [ -n "$3" ]; then |
| 52 | printf " got: %s\n" "$3" |
| 53 | fi |
| 54 | FAILED=$((FAILED + 1)) |
| 55 | } |
| 56 | |
| 57 | skip() { |
| 58 | TEST_NUM=$((TEST_NUM + 1)) |
| 59 | printf "${YELLOW}⊘ SKIP${NC} ${TEST_PREFIX} ${CURRENT_SECTION}.${TEST_NUM}: %s - %s\n" "$1" "$2" |
| 60 | SKIPPED=$((SKIPPED + 1)) |
| 61 | } |
| 62 | |
| 63 | section() { |
| 64 | CURRENT_SECTION=$(echo "$1" | grep -oE '^[0-9]+' || echo "0") |
| 65 | TEST_NUM=0 |
| 66 | printf "\n" |
| 67 | printf "${BLUE}==========================================\n" |
| 68 | printf "%s\n" "$1" |
| 69 | printf "==========================================${NC}\n" |
| 70 | } |
| 71 | |
| 72 | # Create test directory with test files |
| 73 | setup_test_files() { |
| 74 | TEST_DIR="/tmp/shell_filetest_$$" |
| 75 | mkdir -p "$TEST_DIR" |
| 76 | cd "$TEST_DIR" || exit 1 |
| 77 | |
| 78 | # Create various test files |
| 79 | echo "content" > regular_file |
| 80 | mkdir test_dir |
| 81 | touch empty_file |
| 82 | chmod 755 executable_file 2>/dev/null || touch executable_file |
| 83 | chmod +x executable_file 2>/dev/null |
| 84 | chmod 000 unreadable_file 2>/dev/null || touch unreadable_file |
| 85 | ln -s regular_file symlink_file 2>/dev/null |
| 86 | ln -s nonexistent broken_link 2>/dev/null |
| 87 | mkfifo named_pipe 2>/dev/null || true |
| 88 | } |
| 89 | |
| 90 | cleanup_test_files() { |
| 91 | cd / |
| 92 | chmod 644 "$TEST_DIR/unreadable_file" 2>/dev/null |
| 93 | rm -rf "$TEST_DIR" |
| 94 | } |
| 95 | |
| 96 | # Trap to ensure cleanup |
| 97 | trap cleanup_test_files EXIT |
| 98 | |
| 99 | setup_test_files |
| 100 | |
| 101 | # ===================================== |
| 102 | section "369. FILE EXISTENCE AND TYPE TESTS" |
| 103 | # ===================================== |
| 104 | |
| 105 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e regular_file ] && echo yes || echo no' 2>&1) |
| 106 | if [ "$result" = "yes" ]; then |
| 107 | pass "[ -e file ] exists test (regular file)" |
| 108 | else |
| 109 | fail "[ -e file ] exists test (regular file)" "yes" "$result" |
| 110 | fi |
| 111 | |
| 112 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e test_dir ] && echo yes || echo no' 2>&1) |
| 113 | if [ "$result" = "yes" ]; then |
| 114 | pass "[ -e dir ] exists test (directory)" |
| 115 | else |
| 116 | fail "[ -e dir ] exists test (directory)" "yes" "$result" |
| 117 | fi |
| 118 | |
| 119 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -e nonexistent ] && echo yes || echo no' 2>&1) |
| 120 | if [ "$result" = "no" ]; then |
| 121 | pass "[ -e nonexistent ] returns false" |
| 122 | else |
| 123 | fail "[ -e nonexistent ] returns false" "no" "$result" |
| 124 | fi |
| 125 | |
| 126 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -f regular_file ] && echo yes || echo no' 2>&1) |
| 127 | if [ "$result" = "yes" ]; then |
| 128 | pass "[ -f file ] regular file test" |
| 129 | else |
| 130 | fail "[ -f file ] regular file test" "yes" "$result" |
| 131 | fi |
| 132 | |
| 133 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -f test_dir ] && echo yes || echo no' 2>&1) |
| 134 | if [ "$result" = "no" ]; then |
| 135 | pass "[ -f dir ] returns false for directory" |
| 136 | else |
| 137 | fail "[ -f dir ] returns false for directory" "no" "$result" |
| 138 | fi |
| 139 | |
| 140 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -d test_dir ] && echo yes || echo no' 2>&1) |
| 141 | if [ "$result" = "yes" ]; then |
| 142 | pass "[ -d dir ] directory test" |
| 143 | else |
| 144 | fail "[ -d dir ] directory test" "yes" "$result" |
| 145 | fi |
| 146 | |
| 147 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -d regular_file ] && echo yes || echo no' 2>&1) |
| 148 | if [ "$result" = "no" ]; then |
| 149 | pass "[ -d file ] returns false for file" |
| 150 | else |
| 151 | fail "[ -d file ] returns false for file" "no" "$result" |
| 152 | fi |
| 153 | |
| 154 | # ===================================== |
| 155 | section "370. SYMBOLIC LINK TESTS" |
| 156 | # ===================================== |
| 157 | |
| 158 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L symlink_file ] && echo yes || echo no' 2>&1) |
| 159 | if [ "$result" = "yes" ]; then |
| 160 | pass "[ -L symlink ] symbolic link test" |
| 161 | else |
| 162 | fail "[ -L symlink ] symbolic link test" "yes" "$result" |
| 163 | fi |
| 164 | |
| 165 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -h symlink_file ] && echo yes || echo no' 2>&1) |
| 166 | if [ "$result" = "yes" ]; then |
| 167 | pass "[ -h symlink ] symbolic link test (alias)" |
| 168 | else |
| 169 | fail "[ -h symlink ] symbolic link test (alias)" "yes" "$result" |
| 170 | fi |
| 171 | |
| 172 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L regular_file ] && echo yes || echo no' 2>&1) |
| 173 | if [ "$result" = "no" ]; then |
| 174 | pass "[ -L regular ] returns false for non-symlink" |
| 175 | else |
| 176 | fail "[ -L regular ] returns false for non-symlink" "no" "$result" |
| 177 | fi |
| 178 | |
| 179 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -L broken_link ] && echo yes || echo no' 2>&1) |
| 180 | if [ "$result" = "yes" ]; then |
| 181 | pass "[ -L broken_link ] true for broken symlink" |
| 182 | else |
| 183 | fail "[ -L broken_link ] true for broken symlink" "yes" "$result" |
| 184 | fi |
| 185 | |
| 186 | # ===================================== |
| 187 | section "371. FILE PERMISSION TESTS" |
| 188 | # ===================================== |
| 189 | |
| 190 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -r regular_file ] && echo yes || echo no' 2>&1) |
| 191 | if [ "$result" = "yes" ]; then |
| 192 | pass "[ -r file ] readable test" |
| 193 | else |
| 194 | fail "[ -r file ] readable test" "yes" "$result" |
| 195 | fi |
| 196 | |
| 197 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -w regular_file ] && echo yes || echo no' 2>&1) |
| 198 | if [ "$result" = "yes" ]; then |
| 199 | pass "[ -w file ] writable test" |
| 200 | else |
| 201 | fail "[ -w file ] writable test" "yes" "$result" |
| 202 | fi |
| 203 | |
| 204 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -x executable_file ] && echo yes || echo no' 2>&1) |
| 205 | if [ "$result" = "yes" ]; then |
| 206 | pass "[ -x file ] executable test" |
| 207 | else |
| 208 | fail "[ -x file ] executable test" "yes" "$result" |
| 209 | fi |
| 210 | |
| 211 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -x regular_file ] && echo yes || echo no' 2>&1) |
| 212 | if [ "$result" = "no" ]; then |
| 213 | pass "[ -x non-exec ] returns false" |
| 214 | else |
| 215 | fail "[ -x non-exec ] returns false" "no" "$result" |
| 216 | fi |
| 217 | |
| 218 | # ===================================== |
| 219 | section "372. FILE SIZE TESTS" |
| 220 | # ===================================== |
| 221 | |
| 222 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -s regular_file ] && echo yes || echo no' 2>&1) |
| 223 | if [ "$result" = "yes" ]; then |
| 224 | pass "[ -s file ] size greater than zero" |
| 225 | else |
| 226 | fail "[ -s file ] size greater than zero" "yes" "$result" |
| 227 | fi |
| 228 | |
| 229 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -s empty_file ] && echo yes || echo no' 2>&1) |
| 230 | if [ "$result" = "no" ]; then |
| 231 | pass "[ -s empty ] returns false for empty file" |
| 232 | else |
| 233 | fail "[ -s empty ] returns false for empty file" "no" "$result" |
| 234 | fi |
| 235 | |
| 236 | # ===================================== |
| 237 | section "373. STRING TESTS" |
| 238 | # ===================================== |
| 239 | |
| 240 | result=$("$SHELL_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1) |
| 241 | if [ "$result" = "yes" ]; then |
| 242 | pass "[ -z \"\" ] zero length string" |
| 243 | else |
| 244 | fail "[ -z \"\" ] zero length string" "yes" "$result" |
| 245 | fi |
| 246 | |
| 247 | result=$("$SHELL_BIN" -c '[ -z "hello" ] && echo yes || echo no' 2>&1) |
| 248 | if [ "$result" = "no" ]; then |
| 249 | pass "[ -z str ] returns false for non-empty" |
| 250 | else |
| 251 | fail "[ -z str ] returns false for non-empty" "no" "$result" |
| 252 | fi |
| 253 | |
| 254 | result=$("$SHELL_BIN" -c '[ -n "hello" ] && echo yes || echo no' 2>&1) |
| 255 | if [ "$result" = "yes" ]; then |
| 256 | pass "[ -n str ] non-zero length string" |
| 257 | else |
| 258 | fail "[ -n str ] non-zero length string" "yes" "$result" |
| 259 | fi |
| 260 | |
| 261 | result=$("$SHELL_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1) |
| 262 | if [ "$result" = "no" ]; then |
| 263 | pass "[ -n \"\" ] returns false for empty" |
| 264 | else |
| 265 | fail "[ -n \"\" ] returns false for empty" "no" "$result" |
| 266 | fi |
| 267 | |
| 268 | result=$("$SHELL_BIN" -c '[ "hello" ] && echo yes || echo no' 2>&1) |
| 269 | if [ "$result" = "yes" ]; then |
| 270 | pass "[ string ] implicit non-empty test" |
| 271 | else |
| 272 | fail "[ string ] implicit non-empty test" "yes" "$result" |
| 273 | fi |
| 274 | |
| 275 | result=$("$SHELL_BIN" -c '[ "" ] && echo yes || echo no' 2>&1) |
| 276 | if [ "$result" = "no" ]; then |
| 277 | pass "[ \"\" ] empty string is false" |
| 278 | else |
| 279 | fail "[ \"\" ] empty string is false" "no" "$result" |
| 280 | fi |
| 281 | |
| 282 | # ===================================== |
| 283 | section "374. STRING COMPARISON TESTS" |
| 284 | # ===================================== |
| 285 | |
| 286 | result=$("$SHELL_BIN" -c '[ "abc" = "abc" ] && echo yes || echo no' 2>&1) |
| 287 | if [ "$result" = "yes" ]; then |
| 288 | pass "[ str = str ] string equality" |
| 289 | else |
| 290 | fail "[ str = str ] string equality" "yes" "$result" |
| 291 | fi |
| 292 | |
| 293 | result=$("$SHELL_BIN" -c '[ "abc" = "xyz" ] && echo yes || echo no' 2>&1) |
| 294 | if [ "$result" = "no" ]; then |
| 295 | pass "[ str1 = str2 ] returns false for different" |
| 296 | else |
| 297 | fail "[ str1 = str2 ] returns false for different" "no" "$result" |
| 298 | fi |
| 299 | |
| 300 | result=$("$SHELL_BIN" -c '[ "abc" != "xyz" ] && echo yes || echo no' 2>&1) |
| 301 | if [ "$result" = "yes" ]; then |
| 302 | pass "[ str1 != str2 ] string inequality" |
| 303 | else |
| 304 | fail "[ str1 != str2 ] string inequality" "yes" "$result" |
| 305 | fi |
| 306 | |
| 307 | result=$("$SHELL_BIN" -c '[ "abc" != "abc" ] && echo yes || echo no' 2>&1) |
| 308 | if [ "$result" = "no" ]; then |
| 309 | pass "[ str != str ] returns false for same" |
| 310 | else |
| 311 | fail "[ str != str ] returns false for same" "no" "$result" |
| 312 | fi |
| 313 | |
| 314 | # ===================================== |
| 315 | section "375. NUMERIC COMPARISON TESTS" |
| 316 | # ===================================== |
| 317 | |
| 318 | result=$("$SHELL_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1) |
| 319 | if [ "$result" = "yes" ]; then |
| 320 | pass "[ n -eq n ] numeric equality" |
| 321 | else |
| 322 | fail "[ n -eq n ] numeric equality" "yes" "$result" |
| 323 | fi |
| 324 | |
| 325 | result=$("$SHELL_BIN" -c '[ 5 -eq 3 ] && echo yes || echo no' 2>&1) |
| 326 | if [ "$result" = "no" ]; then |
| 327 | pass "[ n1 -eq n2 ] returns false for different" |
| 328 | else |
| 329 | fail "[ n1 -eq n2 ] returns false for different" "no" "$result" |
| 330 | fi |
| 331 | |
| 332 | result=$("$SHELL_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1) |
| 333 | if [ "$result" = "yes" ]; then |
| 334 | pass "[ n1 -ne n2 ] numeric inequality" |
| 335 | else |
| 336 | fail "[ n1 -ne n2 ] numeric inequality" "yes" "$result" |
| 337 | fi |
| 338 | |
| 339 | result=$("$SHELL_BIN" -c '[ 5 -gt 3 ] && echo yes || echo no' 2>&1) |
| 340 | if [ "$result" = "yes" ]; then |
| 341 | pass "[ n1 -gt n2 ] greater than" |
| 342 | else |
| 343 | fail "[ n1 -gt n2 ] greater than" "yes" "$result" |
| 344 | fi |
| 345 | |
| 346 | result=$("$SHELL_BIN" -c '[ 3 -gt 5 ] && echo yes || echo no' 2>&1) |
| 347 | if [ "$result" = "no" ]; then |
| 348 | pass "[ n1 -gt n2 ] returns false when not greater" |
| 349 | else |
| 350 | fail "[ n1 -gt n2 ] returns false when not greater" "no" "$result" |
| 351 | fi |
| 352 | |
| 353 | result=$("$SHELL_BIN" -c '[ 5 -ge 5 ] && echo yes || echo no' 2>&1) |
| 354 | if [ "$result" = "yes" ]; then |
| 355 | pass "[ n -ge n ] greater or equal (equal)" |
| 356 | else |
| 357 | fail "[ n -ge n ] greater or equal (equal)" "yes" "$result" |
| 358 | fi |
| 359 | |
| 360 | result=$("$SHELL_BIN" -c '[ 5 -ge 3 ] && echo yes || echo no' 2>&1) |
| 361 | if [ "$result" = "yes" ]; then |
| 362 | pass "[ n1 -ge n2 ] greater or equal (greater)" |
| 363 | else |
| 364 | fail "[ n1 -ge n2 ] greater or equal (greater)" "yes" "$result" |
| 365 | fi |
| 366 | |
| 367 | result=$("$SHELL_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1) |
| 368 | if [ "$result" = "yes" ]; then |
| 369 | pass "[ n1 -lt n2 ] less than" |
| 370 | else |
| 371 | fail "[ n1 -lt n2 ] less than" "yes" "$result" |
| 372 | fi |
| 373 | |
| 374 | result=$("$SHELL_BIN" -c '[ 5 -lt 3 ] && echo yes || echo no' 2>&1) |
| 375 | if [ "$result" = "no" ]; then |
| 376 | pass "[ n1 -lt n2 ] returns false when not less" |
| 377 | else |
| 378 | fail "[ n1 -lt n2 ] returns false when not less" "no" "$result" |
| 379 | fi |
| 380 | |
| 381 | result=$("$SHELL_BIN" -c '[ 5 -le 5 ] && echo yes || echo no' 2>&1) |
| 382 | if [ "$result" = "yes" ]; then |
| 383 | pass "[ n -le n ] less or equal (equal)" |
| 384 | else |
| 385 | fail "[ n -le n ] less or equal (equal)" "yes" "$result" |
| 386 | fi |
| 387 | |
| 388 | result=$("$SHELL_BIN" -c '[ 3 -le 5 ] && echo yes || echo no' 2>&1) |
| 389 | if [ "$result" = "yes" ]; then |
| 390 | pass "[ n1 -le n2 ] less or equal (less)" |
| 391 | else |
| 392 | fail "[ n1 -le n2 ] less or equal (less)" "yes" "$result" |
| 393 | fi |
| 394 | |
| 395 | # ===================================== |
| 396 | section "376. LOGICAL OPERATORS" |
| 397 | # ===================================== |
| 398 | |
| 399 | result=$("$SHELL_BIN" -c '[ ! -e /nonexistent ] && echo yes || echo no' 2>&1) |
| 400 | if [ "$result" = "yes" ]; then |
| 401 | pass "[ ! expr ] negation" |
| 402 | else |
| 403 | fail "[ ! expr ] negation" "yes" "$result" |
| 404 | fi |
| 405 | |
| 406 | result=$("$SHELL_BIN" -c '[ ! -d /tmp ] && echo yes || echo no' 2>&1) |
| 407 | if [ "$result" = "no" ]; then |
| 408 | pass "[ ! expr ] negation of true" |
| 409 | else |
| 410 | fail "[ ! expr ] negation of true" "no" "$result" |
| 411 | fi |
| 412 | |
| 413 | result=$("$SHELL_BIN" -c '[ -d /tmp -a -e /tmp ] && echo yes || echo no' 2>&1) |
| 414 | if [ "$result" = "yes" ]; then |
| 415 | pass "[ expr -a expr ] logical AND (both true)" |
| 416 | else |
| 417 | fail "[ expr -a expr ] logical AND (both true)" "yes" "$result" |
| 418 | fi |
| 419 | |
| 420 | result=$("$SHELL_BIN" -c '[ -d /tmp -a -e /nonexistent ] && echo yes || echo no' 2>&1) |
| 421 | if [ "$result" = "no" ]; then |
| 422 | pass "[ expr -a expr ] logical AND (one false)" |
| 423 | else |
| 424 | fail "[ expr -a expr ] logical AND (one false)" "no" "$result" |
| 425 | fi |
| 426 | |
| 427 | result=$("$SHELL_BIN" -c '[ -e /nonexistent -o -d /tmp ] && echo yes || echo no' 2>&1) |
| 428 | if [ "$result" = "yes" ]; then |
| 429 | pass "[ expr -o expr ] logical OR (one true)" |
| 430 | else |
| 431 | fail "[ expr -o expr ] logical OR (one true)" "yes" "$result" |
| 432 | fi |
| 433 | |
| 434 | result=$("$SHELL_BIN" -c '[ -e /nonexistent -o -e /alsononexistent ] && echo yes || echo no' 2>&1) |
| 435 | if [ "$result" = "no" ]; then |
| 436 | pass "[ expr -o expr ] logical OR (both false)" |
| 437 | else |
| 438 | fail "[ expr -o expr ] logical OR (both false)" "no" "$result" |
| 439 | fi |
| 440 | |
| 441 | # ===================================== |
| 442 | section "377. FILE COMPARISON TESTS" |
| 443 | # ===================================== |
| 444 | |
| 445 | # Create files with different timestamps |
| 446 | touch "$TEST_DIR/older_file" |
| 447 | sleep 1 |
| 448 | touch "$TEST_DIR/newer_file" |
| 449 | |
| 450 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ newer_file -nt older_file ] && echo yes || echo no' 2>&1) |
| 451 | if [ "$result" = "yes" ]; then |
| 452 | pass "[ f1 -nt f2 ] newer than test" |
| 453 | else |
| 454 | fail "[ f1 -nt f2 ] newer than test" "yes" "$result" |
| 455 | fi |
| 456 | |
| 457 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ older_file -ot newer_file ] && echo yes || echo no' 2>&1) |
| 458 | if [ "$result" = "yes" ]; then |
| 459 | pass "[ f1 -ot f2 ] older than test" |
| 460 | else |
| 461 | fail "[ f1 -ot f2 ] older than test" "yes" "$result" |
| 462 | fi |
| 463 | |
| 464 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ regular_file -ef regular_file ] && echo yes || echo no' 2>&1) |
| 465 | if [ "$result" = "yes" ]; then |
| 466 | pass "[ f -ef f ] same file test" |
| 467 | else |
| 468 | fail "[ f -ef f ] same file test" "yes" "$result" |
| 469 | fi |
| 470 | |
| 471 | # ===================================== |
| 472 | section "378. TEST COMMAND FORM" |
| 473 | # ===================================== |
| 474 | |
| 475 | result=$("$SHELL_BIN" -c 'test -d /tmp && echo yes || echo no' 2>&1) |
| 476 | if [ "$result" = "yes" ]; then |
| 477 | pass "test -d dir (test command form)" |
| 478 | else |
| 479 | fail "test -d dir (test command form)" "yes" "$result" |
| 480 | fi |
| 481 | |
| 482 | result=$("$SHELL_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1) |
| 483 | if [ "$result" = "yes" ]; then |
| 484 | pass "test str = str (test command form)" |
| 485 | else |
| 486 | fail "test str = str (test command form)" "yes" "$result" |
| 487 | fi |
| 488 | |
| 489 | result=$("$SHELL_BIN" -c 'test 5 -gt 3 && echo yes || echo no' 2>&1) |
| 490 | if [ "$result" = "yes" ]; then |
| 491 | pass "test n1 -gt n2 (test command form)" |
| 492 | else |
| 493 | fail "test n1 -gt n2 (test command form)" "yes" "$result" |
| 494 | fi |
| 495 | |
| 496 | # ===================================== |
| 497 | section "379. SPECIAL FILE TYPES" |
| 498 | # ===================================== |
| 499 | |
| 500 | # Named pipe test (if created successfully) |
| 501 | if [ -p "$TEST_DIR/named_pipe" ]; then |
| 502 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -p named_pipe ] && echo yes || echo no' 2>&1) |
| 503 | if [ "$result" = "yes" ]; then |
| 504 | pass "[ -p fifo ] named pipe test" |
| 505 | else |
| 506 | fail "[ -p fifo ] named pipe test" "yes" "$result" |
| 507 | fi |
| 508 | else |
| 509 | skip "[ -p fifo ] named pipe test" "mkfifo not available" |
| 510 | fi |
| 511 | |
| 512 | result=$("$SHELL_BIN" -c 'cd '"$TEST_DIR"' && [ -p regular_file ] && echo yes || echo no' 2>&1) |
| 513 | if [ "$result" = "no" ]; then |
| 514 | pass "[ -p regular ] returns false for non-pipe" |
| 515 | else |
| 516 | fail "[ -p regular ] returns false for non-pipe" "no" "$result" |
| 517 | fi |
| 518 | |
| 519 | # Terminal test |
| 520 | result=$("$SHELL_BIN" -c '[ -t 0 ] && echo yes || echo no' 2>&1) |
| 521 | # Since we're running non-interactively, stdin is not a terminal |
| 522 | if [ "$result" = "no" ]; then |
| 523 | pass "[ -t 0 ] non-terminal stdin" |
| 524 | else |
| 525 | fail "[ -t 0 ] non-terminal stdin" "no" "$result" |
| 526 | fi |
| 527 | |
| 528 | # ===================================== |
| 529 | section "380. EDGE CASES" |
| 530 | # ===================================== |
| 531 | |
| 532 | result=$("$SHELL_BIN" -c '[ ] && echo yes || echo no' 2>&1) |
| 533 | if [ "$result" = "no" ]; then |
| 534 | pass "[ ] empty test returns false" |
| 535 | else |
| 536 | fail "[ ] empty test returns false" "no" "$result" |
| 537 | fi |
| 538 | |
| 539 | result=$("$SHELL_BIN" -c 'x=""; [ -n "$x" ] && echo yes || echo no' 2>&1) |
| 540 | if [ "$result" = "no" ]; then |
| 541 | pass "[ -n \"\$empty\" ] with empty variable" |
| 542 | else |
| 543 | fail "[ -n \"\$empty\" ] with empty variable" "no" "$result" |
| 544 | fi |
| 545 | |
| 546 | result=$("$SHELL_BIN" -c 'x="hello"; [ -n "$x" ] && echo yes || echo no' 2>&1) |
| 547 | if [ "$result" = "yes" ]; then |
| 548 | pass "[ -n \"\$var\" ] with non-empty variable" |
| 549 | else |
| 550 | fail "[ -n \"\$var\" ] with non-empty variable" "yes" "$result" |
| 551 | fi |
| 552 | |
| 553 | result=$("$SHELL_BIN" -c '[ "=" = "=" ] && echo yes || echo no' 2>&1) |
| 554 | if [ "$result" = "yes" ]; then |
| 555 | pass "[ \"=\" = \"=\" ] equals sign as string" |
| 556 | else |
| 557 | fail "[ \"=\" = \"=\" ] equals sign as string" "yes" "$result" |
| 558 | fi |
| 559 | |
| 560 | result=$("$SHELL_BIN" -c '[ "-n" = "-n" ] && echo yes || echo no' 2>&1) |
| 561 | if [ "$result" = "yes" ]; then |
| 562 | pass "[ \"-n\" = \"-n\" ] operator as string" |
| 563 | else |
| 564 | fail "[ \"-n\" = \"-n\" ] operator as string" "yes" "$result" |
| 565 | fi |
| 566 | |
| 567 | # ===================================== |
| 568 | section "381. COMPLEX TEST EXPRESSIONS" |
| 569 | # ===================================== |
| 570 | |
| 571 | result=$("$SHELL_BIN" -c '[ 1 -eq 1 -a 2 -eq 2 ] && echo yes || echo no' 2>&1) |
| 572 | if [ "$result" = "yes" ]; then |
| 573 | pass "[ a -a b ] both true" |
| 574 | else |
| 575 | fail "[ a -a b ] both true" "yes" "$result" |
| 576 | fi |
| 577 | |
| 578 | result=$("$SHELL_BIN" -c '[ 1 -eq 1 -a 2 -eq 3 ] && echo yes || echo no' 2>&1) |
| 579 | if [ "$result" = "no" ]; then |
| 580 | pass "[ a -a b ] second false" |
| 581 | else |
| 582 | fail "[ a -a b ] second false" "no" "$result" |
| 583 | fi |
| 584 | |
| 585 | result=$("$SHELL_BIN" -c '[ 1 -eq 2 -o 2 -eq 2 ] && echo yes || echo no' 2>&1) |
| 586 | if [ "$result" = "yes" ]; then |
| 587 | pass "[ a -o b ] second true" |
| 588 | else |
| 589 | fail "[ a -o b ] second true" "yes" "$result" |
| 590 | fi |
| 591 | |
| 592 | result=$("$SHELL_BIN" -c '[ 1 -eq 2 -o 3 -eq 4 ] && echo yes || echo no' 2>&1) |
| 593 | if [ "$result" = "no" ]; then |
| 594 | pass "[ a -o b ] both false" |
| 595 | else |
| 596 | fail "[ a -o b ] both false" "no" "$result" |
| 597 | fi |
| 598 | |
| 599 | result=$("$SHELL_BIN" -c '[ ! 1 -eq 2 ] && echo yes || echo no' 2>&1) |
| 600 | if [ "$result" = "yes" ]; then |
| 601 | pass "[ ! expr ] negates false" |
| 602 | else |
| 603 | fail "[ ! expr ] negates false" "yes" "$result" |
| 604 | fi |
| 605 | |
| 606 | result=$("$SHELL_BIN" -c '[ ! 1 -eq 1 ] && echo yes || echo no' 2>&1) |
| 607 | if [ "$result" = "no" ]; then |
| 608 | pass "[ ! expr ] negates true" |
| 609 | else |
| 610 | fail "[ ! expr ] negates true" "no" "$result" |
| 611 | fi |
| 612 | |
| 613 | # ===================================== |
| 614 | section "382. PARENTHESES IN TEST" |
| 615 | # ===================================== |
| 616 | |
| 617 | result=$("$SHELL_BIN" -c '[ \( 1 -eq 1 \) ] && echo yes || echo no' 2>&1) |
| 618 | if [ "$result" = "yes" ]; then |
| 619 | pass "[ \\( expr \\) ] parentheses" |
| 620 | else |
| 621 | fail "[ \\( expr \\) ] parentheses" "yes" "$result" |
| 622 | fi |
| 623 | |
| 624 | result=$("$SHELL_BIN" -c '[ \( 1 -eq 1 -o 2 -eq 3 \) -a 3 -eq 3 ] && echo yes || echo no' 2>&1) |
| 625 | if [ "$result" = "yes" ]; then |
| 626 | pass "[ \\( a -o b \\) -a c ] complex grouping" |
| 627 | else |
| 628 | fail "[ \\( a -o b \\) -a c ] complex grouping" "yes" "$result" |
| 629 | fi |
| 630 | |
| 631 | # ===================================== |
| 632 | section "383. STRING LENGTH COMPARISONS" |
| 633 | # ===================================== |
| 634 | |
| 635 | result=$("$SHELL_BIN" -c '[ -z "" ] && echo yes || echo no' 2>&1) |
| 636 | if [ "$result" = "yes" ]; then |
| 637 | pass "[ -z \"\" ] empty string is zero length" |
| 638 | else |
| 639 | fail "[ -z \"\" ] empty string is zero length" "yes" "$result" |
| 640 | fi |
| 641 | |
| 642 | result=$("$SHELL_BIN" -c '[ -z "x" ] && echo yes || echo no' 2>&1) |
| 643 | if [ "$result" = "no" ]; then |
| 644 | pass "[ -z \"x\" ] non-empty has length" |
| 645 | else |
| 646 | fail "[ -z \"x\" ] non-empty has length" "no" "$result" |
| 647 | fi |
| 648 | |
| 649 | result=$("$SHELL_BIN" -c '[ -n "" ] && echo yes || echo no' 2>&1) |
| 650 | if [ "$result" = "no" ]; then |
| 651 | pass "[ -n \"\" ] empty has no length" |
| 652 | else |
| 653 | fail "[ -n \"\" ] empty has no length" "no" "$result" |
| 654 | fi |
| 655 | |
| 656 | result=$("$SHELL_BIN" -c '[ -n "abc" ] && echo yes || echo no' 2>&1) |
| 657 | if [ "$result" = "yes" ]; then |
| 658 | pass "[ -n \"abc\" ] string has length" |
| 659 | else |
| 660 | fail "[ -n \"abc\" ] string has length" "yes" "$result" |
| 661 | fi |
| 662 | |
| 663 | # ===================================== |
| 664 | section "384. NUMERIC EDGE CASES" |
| 665 | # ===================================== |
| 666 | |
| 667 | result=$("$SHELL_BIN" -c '[ 0 -eq 0 ] && echo yes || echo no' 2>&1) |
| 668 | if [ "$result" = "yes" ]; then |
| 669 | pass "[ 0 -eq 0 ] zero equals zero" |
| 670 | else |
| 671 | fail "[ 0 -eq 0 ] zero equals zero" "yes" "$result" |
| 672 | fi |
| 673 | |
| 674 | result=$("$SHELL_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1) |
| 675 | if [ "$result" = "yes" ]; then |
| 676 | pass "[ -5 -lt 0 ] negative less than zero" |
| 677 | else |
| 678 | fail "[ -5 -lt 0 ] negative less than zero" "yes" "$result" |
| 679 | fi |
| 680 | |
| 681 | result=$("$SHELL_BIN" -c '[ -10 -gt -20 ] && echo yes || echo no' 2>&1) |
| 682 | if [ "$result" = "yes" ]; then |
| 683 | pass "[ -10 -gt -20 ] negative comparisons" |
| 684 | else |
| 685 | fail "[ -10 -gt -20 ] negative comparisons" "yes" "$result" |
| 686 | fi |
| 687 | |
| 688 | result=$("$SHELL_BIN" -c '[ 999999 -gt 1 ] && echo yes || echo no' 2>&1) |
| 689 | if [ "$result" = "yes" ]; then |
| 690 | pass "[ large -gt 1 ] large numbers" |
| 691 | else |
| 692 | fail "[ large -gt 1 ] large numbers" "yes" "$result" |
| 693 | fi |
| 694 | |
| 695 | # ===================================== |
| 696 | section "385. STRING VS NUMERIC" |
| 697 | # ===================================== |
| 698 | |
| 699 | result=$("$SHELL_BIN" -c '[ "10" = "10" ] && echo yes || echo no' 2>&1) |
| 700 | if [ "$result" = "yes" ]; then |
| 701 | pass "[ \"10\" = \"10\" ] string comparison" |
| 702 | else |
| 703 | fail "[ \"10\" = \"10\" ] string comparison" "yes" "$result" |
| 704 | fi |
| 705 | |
| 706 | result=$("$SHELL_BIN" -c '[ "10" = "010" ] && echo yes || echo no' 2>&1) |
| 707 | if [ "$result" = "no" ]; then |
| 708 | pass "[ \"10\" = \"010\" ] string differs from numeric" |
| 709 | else |
| 710 | fail "[ \"10\" = \"010\" ] string differs from numeric" "no" "$result" |
| 711 | fi |
| 712 | |
| 713 | result=$("$SHELL_BIN" -c '[ 10 -eq 010 ] && echo yes || echo no' 2>&1) |
| 714 | # Numeric comparison - may or may not treat 010 as octal |
| 715 | if [ "$result" = "yes" ] || [ "$result" = "no" ]; then |
| 716 | pass "[ 10 -eq 010 ] numeric comparison" |
| 717 | else |
| 718 | fail "[ 10 -eq 010 ] numeric comparison" "yes or no" "$result" |
| 719 | fi |
| 720 | |
| 721 | # ===================================== |
| 722 | section "386. FILE TEST WITH VARIABLES" |
| 723 | # ===================================== |
| 724 | |
| 725 | result=$("$SHELL_BIN" -c 'f='"$TEST_DIR"'/regular_file; [ -f "$f" ] && echo yes || echo no' 2>&1) |
| 726 | if [ "$result" = "yes" ]; then |
| 727 | pass "[ -f \"\$var\" ] variable as filename" |
| 728 | else |
| 729 | fail "[ -f \"\$var\" ] variable as filename" "yes" "$result" |
| 730 | fi |
| 731 | |
| 732 | result=$("$SHELL_BIN" -c 'd='"$TEST_DIR"'; [ -d "$d" ] && echo yes || echo no' 2>&1) |
| 733 | if [ "$result" = "yes" ]; then |
| 734 | pass "[ -d \"\$var\" ] variable as dirname" |
| 735 | else |
| 736 | fail "[ -d \"\$var\" ] variable as dirname" "yes" "$result" |
| 737 | fi |
| 738 | |
| 739 | # ===================================== |
| 740 | section "387. EMPTY OPERAND HANDLING" |
| 741 | # ===================================== |
| 742 | |
| 743 | result=$("$SHELL_BIN" -c 'unset x; [ -n "$x" ] && echo yes || echo no' 2>&1) |
| 744 | if [ "$result" = "no" ]; then |
| 745 | pass "[ -n \"\$unset\" ] unset variable" |
| 746 | else |
| 747 | fail "[ -n \"\$unset\" ] unset variable" "no" "$result" |
| 748 | fi |
| 749 | |
| 750 | result=$("$SHELL_BIN" -c 'unset x; [ -z "$x" ] && echo yes || echo no' 2>&1) |
| 751 | if [ "$result" = "yes" ]; then |
| 752 | pass "[ -z \"\$unset\" ] unset is zero length" |
| 753 | else |
| 754 | fail "[ -z \"\$unset\" ] unset is zero length" "yes" "$result" |
| 755 | fi |
| 756 | |
| 757 | result=$("$SHELL_BIN" -c 'unset x; [ "$x" = "" ] && echo yes || echo no' 2>&1) |
| 758 | if [ "$result" = "yes" ]; then |
| 759 | pass "[ \"\$unset\" = \"\" ] unset equals empty" |
| 760 | else |
| 761 | fail "[ \"\$unset\" = \"\" ] unset equals empty" "yes" "$result" |
| 762 | fi |
| 763 | |
| 764 | # ===================================== |
| 765 | section "388. NUMERIC COMPARISON OPERATORS" |
| 766 | # ===================================== |
| 767 | |
| 768 | result=$("$SHELL_BIN" -c '[ 5 -eq 5 ] && echo yes || echo no' 2>&1) |
| 769 | if [ "$result" = "yes" ]; then |
| 770 | pass "[ 5 -eq 5 ] equals" |
| 771 | else |
| 772 | fail "[ 5 -eq 5 ] equals" "yes" "$result" |
| 773 | fi |
| 774 | |
| 775 | result=$("$SHELL_BIN" -c '[ 5 -ne 3 ] && echo yes || echo no' 2>&1) |
| 776 | if [ "$result" = "yes" ]; then |
| 777 | pass "[ 5 -ne 3 ] not equals" |
| 778 | else |
| 779 | fail "[ 5 -ne 3 ] not equals" "yes" "$result" |
| 780 | fi |
| 781 | |
| 782 | result=$("$SHELL_BIN" -c '[ 10 -gt 5 ] && echo yes || echo no' 2>&1) |
| 783 | if [ "$result" = "yes" ]; then |
| 784 | pass "[ 10 -gt 5 ] greater than" |
| 785 | else |
| 786 | fail "[ 10 -gt 5 ] greater than" "yes" "$result" |
| 787 | fi |
| 788 | |
| 789 | result=$("$SHELL_BIN" -c '[ 10 -ge 10 ] && echo yes || echo no' 2>&1) |
| 790 | if [ "$result" = "yes" ]; then |
| 791 | pass "[ 10 -ge 10 ] greater or equal" |
| 792 | else |
| 793 | fail "[ 10 -ge 10 ] greater or equal" "yes" "$result" |
| 794 | fi |
| 795 | |
| 796 | result=$("$SHELL_BIN" -c '[ 3 -lt 5 ] && echo yes || echo no' 2>&1) |
| 797 | if [ "$result" = "yes" ]; then |
| 798 | pass "[ 3 -lt 5 ] less than" |
| 799 | else |
| 800 | fail "[ 3 -lt 5 ] less than" "yes" "$result" |
| 801 | fi |
| 802 | |
| 803 | result=$("$SHELL_BIN" -c '[ 3 -le 3 ] && echo yes || echo no' 2>&1) |
| 804 | if [ "$result" = "yes" ]; then |
| 805 | pass "[ 3 -le 3 ] less or equal" |
| 806 | else |
| 807 | fail "[ 3 -le 3 ] less or equal" "yes" "$result" |
| 808 | fi |
| 809 | |
| 810 | # ===================================== |
| 811 | section "389. NEGATIVE NUMBER TESTS" |
| 812 | # ===================================== |
| 813 | |
| 814 | result=$("$SHELL_BIN" -c '[ -5 -lt 0 ] && echo yes || echo no' 2>&1) |
| 815 | if [ "$result" = "yes" ]; then |
| 816 | pass "[ -5 -lt 0 ] negative less than zero" |
| 817 | else |
| 818 | fail "[ -5 -lt 0 ] negative less than zero" "yes" "$result" |
| 819 | fi |
| 820 | |
| 821 | result=$("$SHELL_BIN" -c '[ -10 -lt -5 ] && echo yes || echo no' 2>&1) |
| 822 | if [ "$result" = "yes" ]; then |
| 823 | pass "[ -10 -lt -5 ] negative comparison" |
| 824 | else |
| 825 | fail "[ -10 -lt -5 ] negative comparison" "yes" "$result" |
| 826 | fi |
| 827 | |
| 828 | result=$("$SHELL_BIN" -c '[ -5 -eq -5 ] && echo yes || echo no' 2>&1) |
| 829 | if [ "$result" = "yes" ]; then |
| 830 | pass "[ -5 -eq -5 ] negative equality" |
| 831 | else |
| 832 | fail "[ -5 -eq -5 ] negative equality" "yes" "$result" |
| 833 | fi |
| 834 | |
| 835 | # ===================================== |
| 836 | section "390. STRING TESTS" |
| 837 | # ===================================== |
| 838 | |
| 839 | result=$("$SHELL_BIN" -c '[ "hello" = "hello" ] && echo yes || echo no' 2>&1) |
| 840 | if [ "$result" = "yes" ]; then |
| 841 | pass "[ \"hello\" = \"hello\" ] string equality" |
| 842 | else |
| 843 | fail "[ \"hello\" = \"hello\" ] string equality" "yes" "$result" |
| 844 | fi |
| 845 | |
| 846 | result=$("$SHELL_BIN" -c '[ "hello" != "world" ] && echo yes || echo no' 2>&1) |
| 847 | if [ "$result" = "yes" ]; then |
| 848 | pass "[ \"hello\" != \"world\" ] string inequality" |
| 849 | else |
| 850 | fail "[ \"hello\" != \"world\" ] string inequality" "yes" "$result" |
| 851 | fi |
| 852 | |
| 853 | result=$("$SHELL_BIN" -c '[ "abc" \< "def" ] && echo yes || echo no' 2>&1) |
| 854 | if [ "$result" = "yes" ]; then |
| 855 | pass "[ \"abc\" < \"def\" ] string less than" |
| 856 | else |
| 857 | fail "[ \"abc\" < \"def\" ] string less than" "yes" "$result" |
| 858 | fi |
| 859 | |
| 860 | result=$("$SHELL_BIN" -c '[ "xyz" \> "abc" ] && echo yes || echo no' 2>&1) |
| 861 | if [ "$result" = "yes" ]; then |
| 862 | pass "[ \"xyz\" > \"abc\" ] string greater than" |
| 863 | else |
| 864 | fail "[ \"xyz\" > \"abc\" ] string greater than" "yes" "$result" |
| 865 | fi |
| 866 | |
| 867 | # ===================================== |
| 868 | section "391. FILE PERMISSION TESTS" |
| 869 | # ===================================== |
| 870 | |
| 871 | touch "$TEST_DIR/readable.txt" |
| 872 | chmod 644 "$TEST_DIR/readable.txt" |
| 873 | result=$("$SHELL_BIN" -c '[ -r "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1) |
| 874 | if [ "$result" = "yes" ]; then |
| 875 | pass "[ -r file ] readable file" |
| 876 | else |
| 877 | fail "[ -r file ] readable file" "yes" "$result" |
| 878 | fi |
| 879 | |
| 880 | result=$("$SHELL_BIN" -c '[ -w "'"$TEST_DIR"'/readable.txt" ] && echo yes || echo no' 2>&1) |
| 881 | if [ "$result" = "yes" ]; then |
| 882 | pass "[ -w file ] writable file" |
| 883 | else |
| 884 | fail "[ -w file ] writable file" "yes" "$result" |
| 885 | fi |
| 886 | |
| 887 | # ===================================== |
| 888 | section "392. TEST BUILTIN vs [ COMMAND" |
| 889 | # ===================================== |
| 890 | |
| 891 | result=$("$SHELL_BIN" -c 'test -f /etc/passwd && echo yes || echo no' 2>&1) |
| 892 | if [ "$result" = "yes" ]; then |
| 893 | pass "test -f /etc/passwd" |
| 894 | else |
| 895 | fail "test -f /etc/passwd" "yes" "$result" |
| 896 | fi |
| 897 | |
| 898 | result=$("$SHELL_BIN" -c 'test 5 -eq 5 && echo yes || echo no' 2>&1) |
| 899 | if [ "$result" = "yes" ]; then |
| 900 | pass "test 5 -eq 5" |
| 901 | else |
| 902 | fail "test 5 -eq 5" "yes" "$result" |
| 903 | fi |
| 904 | |
| 905 | result=$("$SHELL_BIN" -c 'test "hello" = "hello" && echo yes || echo no' 2>&1) |
| 906 | if [ "$result" = "yes" ]; then |
| 907 | pass "test string equality" |
| 908 | else |
| 909 | fail "test string equality" "yes" "$result" |
| 910 | fi |
| 911 | |
| 912 | # ===================================== |
| 913 | section "393. COMBINED LOGICAL TESTS" |
| 914 | # ===================================== |
| 915 | |
| 916 | result=$("$SHELL_BIN" -c '[ 5 -gt 3 ] && [ 10 -gt 5 ] && echo yes || echo no' 2>&1) |
| 917 | if [ "$result" = "yes" ]; then |
| 918 | pass "[ ] && [ ] both true" |
| 919 | else |
| 920 | fail "[ ] && [ ] both true" "yes" "$result" |
| 921 | fi |
| 922 | |
| 923 | result=$("$SHELL_BIN" -c '[ 5 -lt 3 ] || [ 10 -gt 5 ] && echo yes || echo no' 2>&1) |
| 924 | if [ "$result" = "yes" ]; then |
| 925 | pass "[ ] || [ ] one true" |
| 926 | else |
| 927 | fail "[ ] || [ ] one true" "yes" "$result" |
| 928 | fi |
| 929 | |
| 930 | result=$("$SHELL_BIN" -c '! [ 5 -lt 3 ] && echo yes || echo no' 2>&1) |
| 931 | if [ "$result" = "yes" ]; then |
| 932 | pass "! [ ] negation" |
| 933 | else |
| 934 | fail "! [ ] negation" "yes" "$result" |
| 935 | fi |
| 936 | |
| 937 | # ===================================== |
| 938 | section "394. FILE TYPE TESTS" |
| 939 | # ===================================== |
| 940 | |
| 941 | result=$("$SHELL_BIN" -c '[ -f /etc/passwd ] && echo yes || echo no' 2>&1) |
| 942 | if [ "$result" = "yes" ]; then |
| 943 | pass "[ -f /etc/passwd ] regular file" |
| 944 | else |
| 945 | fail "[ -f /etc/passwd ] regular file" "yes" "$result" |
| 946 | fi |
| 947 | |
| 948 | result=$("$SHELL_BIN" -c '[ -d /tmp ] && echo yes || echo no' 2>&1) |
| 949 | if [ "$result" = "yes" ]; then |
| 950 | pass "[ -d /tmp ] directory" |
| 951 | else |
| 952 | fail "[ -d /tmp ] directory" "yes" "$result" |
| 953 | fi |
| 954 | |
| 955 | result=$("$SHELL_BIN" -c '[ -e /etc/passwd ] && echo yes || echo no' 2>&1) |
| 956 | if [ "$result" = "yes" ]; then |
| 957 | pass "[ -e /etc/passwd ] exists" |
| 958 | else |
| 959 | fail "[ -e /etc/passwd ] exists" "yes" "$result" |
| 960 | fi |
| 961 | |
| 962 | result=$("$SHELL_BIN" -c '[ -e /nonexistent/path ] && echo yes || echo no' 2>&1) |
| 963 | if [ "$result" = "no" ]; then |
| 964 | pass "[ -e /nonexistent ] does not exist" |
| 965 | else |
| 966 | fail "[ -e /nonexistent ] does not exist" "no" "$result" |
| 967 | fi |
| 968 | |
| 969 | # ===================================== |
| 970 | section "395. FILE SIZE TESTS" |
| 971 | # ===================================== |
| 972 | |
| 973 | echo "content" > "$TEST_DIR/nonempty.txt" |
| 974 | result=$("$SHELL_BIN" -c '[ -s "'"$TEST_DIR"'/nonempty.txt" ] && echo yes || echo no' 2>&1) |
| 975 | if [ "$result" = "yes" ]; then |
| 976 | pass "[ -s file ] non-empty file" |
| 977 | else |
| 978 | fail "[ -s file ] non-empty file" "yes" "$result" |
| 979 | fi |
| 980 | |
| 981 | : > "$TEST_DIR/empty.txt" |
| 982 | result=$("$SHELL_BIN" -c '[ -s "'"$TEST_DIR"'/empty.txt" ] && echo yes || echo no' 2>&1) |
| 983 | if [ "$result" = "no" ]; then |
| 984 | pass "[ -s file ] empty file is false" |
| 985 | else |
| 986 | fail "[ -s file ] empty file is false" "no" "$result" |
| 987 | fi |
| 988 | |
| 989 | # ===================================== |
| 990 | section "396. SYMLINK TESTS" |
| 991 | # ===================================== |
| 992 | |
| 993 | ln -sf /etc/passwd "$TEST_DIR/link_to_passwd" 2>/dev/null || true |
| 994 | result=$("$SHELL_BIN" -c '[ -L "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1) |
| 995 | if [ "$result" = "yes" ]; then |
| 996 | pass "[ -L symlink ] is symlink" |
| 997 | else |
| 998 | fail "[ -L symlink ] is symlink" "yes" "$result" |
| 999 | fi |
| 1000 | |
| 1001 | result=$("$SHELL_BIN" -c '[ -h "'"$TEST_DIR"'/link_to_passwd" ] && echo yes || echo no' 2>&1) |
| 1002 | if [ "$result" = "yes" ]; then |
| 1003 | pass "[ -h symlink ] is symlink (alternate)" |
| 1004 | else |
| 1005 | fail "[ -h symlink ] is symlink (alternate)" "yes" "$result" |
| 1006 | fi |
| 1007 | |
| 1008 | # ===================================== |
| 1009 | section "397. SPECIAL FILE TESTS" |
| 1010 | # ===================================== |
| 1011 | |
| 1012 | result=$("$SHELL_BIN" -c '[ -c /dev/null ] && echo yes || echo no' 2>&1) |
| 1013 | if [ "$result" = "yes" ]; then |
| 1014 | pass "[ -c /dev/null ] character device" |
| 1015 | else |
| 1016 | fail "[ -c /dev/null ] character device" "yes" "$result" |
| 1017 | fi |
| 1018 | |
| 1019 | result=$("$SHELL_BIN" -c '[ -p /dev/null ] && echo yes || echo no' 2>&1) |
| 1020 | if [ "$result" = "no" ]; then |
| 1021 | pass "[ -p /dev/null ] not a pipe" |
| 1022 | else |
| 1023 | fail "[ -p /dev/null ] not a pipe" "no" "$result" |
| 1024 | fi |
| 1025 | |
| 1026 | # ===================================== |
| 1027 | section "398. TERMINAL TESTS" |
| 1028 | # ===================================== |
| 1029 | |
| 1030 | result=$("$SHELL_BIN" -c '[ -t 1 ] && echo tty || echo not_tty' 2>&1) |
| 1031 | # When running in a script, stdout is typically not a tty |
| 1032 | if echo "$result" | grep -qE "(tty|not_tty)"; then |
| 1033 | pass "[ -t 1 ] terminal test runs" |
| 1034 | else |
| 1035 | fail "[ -t 1 ] terminal test runs" |
| 1036 | fi |
| 1037 | |
| 1038 | # ===================================== |
| 1039 | section "399. COMPOUND EXPRESSION PRECEDENCE" |
| 1040 | # ===================================== |
| 1041 | |
| 1042 | result=$("$SHELL_BIN" -c '[ 1 -eq 1 ] && [ 2 -eq 2 ] && [ 3 -eq 3 ] && echo yes || echo no' 2>&1) |
| 1043 | if [ "$result" = "yes" ]; then |
| 1044 | pass "Multiple && chain" |
| 1045 | else |
| 1046 | fail "Multiple && chain" "yes" "$result" |
| 1047 | fi |
| 1048 | |
| 1049 | result=$("$SHELL_BIN" -c '[ 1 -eq 2 ] || [ 2 -eq 2 ] && echo yes || echo no' 2>&1) |
| 1050 | if [ "$result" = "yes" ]; then |
| 1051 | pass "|| then && precedence" |
| 1052 | else |
| 1053 | fail "|| then && precedence" "yes" "$result" |
| 1054 | fi |
| 1055 | |
| 1056 | # ===================================== |
| 1057 | section "400. EDGE CASE EXPRESSIONS" |
| 1058 | # ===================================== |
| 1059 | |
| 1060 | result=$("$SHELL_BIN" -c '[ "" ] && echo yes || echo no' 2>&1) |
| 1061 | if [ "$result" = "no" ]; then |
| 1062 | pass "[ \"\" ] empty string is false" |
| 1063 | else |
| 1064 | fail "[ \"\" ] empty string is false" "no" "$result" |
| 1065 | fi |
| 1066 | |
| 1067 | result=$("$SHELL_BIN" -c '[ "x" ] && echo yes || echo no' 2>&1) |
| 1068 | if [ "$result" = "yes" ]; then |
| 1069 | pass "[ \"x\" ] non-empty string is true" |
| 1070 | else |
| 1071 | fail "[ \"x\" ] non-empty string is true" "yes" "$result" |
| 1072 | fi |
| 1073 | |
| 1074 | result=$("$SHELL_BIN" -c '[ 0 ] && echo yes || echo no' 2>&1) |
| 1075 | if [ "$result" = "yes" ]; then |
| 1076 | pass "[ 0 ] zero string is true (not numeric)" |
| 1077 | else |
| 1078 | fail "[ 0 ] zero string is true (not numeric)" "yes" "$result" |
| 1079 | fi |
| 1080 | |
| 1081 | result=$("$SHELL_BIN" -c '[ ! "" ] && echo yes || echo no' 2>&1) |
| 1082 | if [ "$result" = "yes" ]; then |
| 1083 | pass "[ ! \"\" ] negated empty is true" |
| 1084 | else |
| 1085 | fail "[ ! \"\" ] negated empty is true" "yes" "$result" |
| 1086 | fi |
| 1087 | |
| 1088 | # ===================================== |
| 1089 | # Summary |
| 1090 | # ===================================== |
| 1091 | printf "\n" |
| 1092 | printf "${BLUE}==========================================\n" |
| 1093 | printf "POSIX File Test Operators Summary\n" |
| 1094 | printf "==========================================${NC}\n" |
| 1095 | printf "Passed: ${GREEN}%d${NC}\n" "$PASSED" |
| 1096 | printf "Failed: ${RED}%d${NC}\n" "$FAILED" |
| 1097 | printf "Skipped: ${YELLOW}%d${NC}\n" "$SKIPPED" |
| 1098 | printf "Total: %d\n" "$((PASSED + FAILED + SKIPPED))" |
| 1099 | |
| 1100 | if [ -n "$FAILED_TESTS_LIST" ]; then |
| 1101 | printf "\n${RED}Failed tests:${NC}\n" |
| 1102 | printf "%b" "$FAILED_TESTS_LIST" |
| 1103 | fi |
| 1104 | |
| 1105 | if [ "$FAILED" -gt 0 ]; then |
| 1106 | exit 1 |
| 1107 | fi |
| 1108 | exit 0 |