Bash · 34370 bytes Raw Blame History
1 #!/bin/sh
2 # =====================================
3 # POSIX Compliance File Test Operators Suite for fortsh
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 FORTSH_BIN="${FORTSH_BIN:-$SCRIPT_DIR/../bin/fortsh}"
28
29 # Check if fortsh exists
30 if [ ! -x "$FORTSH_BIN" ]; then
31 printf "${RED}ERROR${NC}: fortsh binary not found at $FORTSH_BIN\n"
32 printf "Please run 'make' first or set FORTSH_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/fortsh_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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=$("$FORTSH_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