fortrangoingonforty/fortsh / 115ba7b

Browse files

Add printf builtin and file test operator test suites

New test files document implementation gaps:
- posix_compliance_printf.sh: 41 tests (24 pass, 17 fail)
- Missing: width/precision specifiers, zero padding, %b format
- Missing: dynamic width (%*s), alternate forms (%#x)
- posix_compliance_filetest.sh: 58 tests (53 pass, 5 fail)
- Missing: logical operators (-a, -o, !) edge cases
- Missing: implicit string test [ string ]
Authored by espadonne
SHA
115ba7b90f3b0376cf619d59efc731b6b611ed30
Parents
ef6c36e
Tree
c46b97f

3 changed files

StatusFile+-
A tests/posix_compliance_filetest.sh 587 0
A tests/posix_compliance_printf.sh 428 0
M tests/run_all_tests.sh 2 0
tests/posix_compliance_filetest.shadded
@@ -0,0 +1,587 @@
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
+# Summary
569
+# =====================================
570
+printf "\n"
571
+printf "${BLUE}==========================================\n"
572
+printf "POSIX File Test Operators Summary\n"
573
+printf "==========================================${NC}\n"
574
+printf "Passed:  ${GREEN}%d${NC}\n" "$PASSED"
575
+printf "Failed:  ${RED}%d${NC}\n" "$FAILED"
576
+printf "Skipped: ${YELLOW}%d${NC}\n" "$SKIPPED"
577
+printf "Total:   %d\n" "$((PASSED + FAILED + SKIPPED))"
578
+
579
+if [ -n "$FAILED_TESTS_LIST" ]; then
580
+    printf "\n${RED}Failed tests:${NC}\n"
581
+    printf "%b" "$FAILED_TESTS_LIST"
582
+fi
583
+
584
+if [ "$FAILED" -gt 0 ]; then
585
+    exit 1
586
+fi
587
+exit 0
tests/posix_compliance_printf.shadded
@@ -0,0 +1,428 @@
1
+#!/bin/sh
2
+# =====================================
3
+# POSIX Compliance printf Builtin Test Suite for fortsh
4
+# =====================================
5
+# Tests the printf builtin command per IEEE Std 1003.1-2017
6
+# Section: Shell & Utilities - printf
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-printf]"
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
+# =====================================
73
+section "358. PRINTF BASIC STRING FORMAT %s"
74
+# =====================================
75
+
76
+result=$("$FORTSH_BIN" -c 'printf "%s\n" "hello"' 2>&1)
77
+if [ "$result" = "hello" ]; then
78
+    pass "printf %s basic string"
79
+else
80
+    fail "printf %s basic string" "hello" "$result"
81
+fi
82
+
83
+result=$("$FORTSH_BIN" -c 'printf "%s %s\n" "hello" "world"' 2>&1)
84
+if [ "$result" = "hello world" ]; then
85
+    pass "printf %s multiple arguments"
86
+else
87
+    fail "printf %s multiple arguments" "hello world" "$result"
88
+fi
89
+
90
+result=$("$FORTSH_BIN" -c 'printf "%s" ""' 2>&1)
91
+if [ "$result" = "" ]; then
92
+    pass "printf %s empty string"
93
+else
94
+    fail "printf %s empty string" "(empty)" "$result"
95
+fi
96
+
97
+result=$("$FORTSH_BIN" -c 'printf "%.3s\n" "hello"' 2>&1)
98
+if [ "$result" = "hel" ]; then
99
+    pass "printf %.3s precision truncates"
100
+else
101
+    fail "printf %.3s precision truncates" "hel" "$result"
102
+fi
103
+
104
+result=$("$FORTSH_BIN" -c 'printf "%10s\n" "hi"' 2>&1)
105
+if [ "$result" = "        hi" ]; then
106
+    pass "printf %10s width right-align"
107
+else
108
+    fail "printf %10s width right-align" "        hi" "$result"
109
+fi
110
+
111
+result=$("$FORTSH_BIN" -c 'printf "%-10s|\n" "hi"' 2>&1)
112
+if [ "$result" = "hi        |" ]; then
113
+    pass "printf %-10s width left-align"
114
+else
115
+    fail "printf %-10s width left-align" "hi        |" "$result"
116
+fi
117
+
118
+# =====================================
119
+section "359. PRINTF INTEGER FORMATS %d %i"
120
+# =====================================
121
+
122
+result=$("$FORTSH_BIN" -c 'printf "%d\n" 42' 2>&1)
123
+if [ "$result" = "42" ]; then
124
+    pass "printf %d basic decimal"
125
+else
126
+    fail "printf %d basic decimal" "42" "$result"
127
+fi
128
+
129
+result=$("$FORTSH_BIN" -c 'printf "%i\n" 42' 2>&1)
130
+if [ "$result" = "42" ]; then
131
+    pass "printf %i basic integer"
132
+else
133
+    fail "printf %i basic integer" "42" "$result"
134
+fi
135
+
136
+result=$("$FORTSH_BIN" -c 'printf "%d\n" -42' 2>&1)
137
+if [ "$result" = "-42" ]; then
138
+    pass "printf %d negative number"
139
+else
140
+    fail "printf %d negative number" "-42" "$result"
141
+fi
142
+
143
+result=$("$FORTSH_BIN" -c 'printf "%5d\n" 42' 2>&1)
144
+if [ "$result" = "   42" ]; then
145
+    pass "printf %5d width padding"
146
+else
147
+    fail "printf %5d width padding" "   42" "$result"
148
+fi
149
+
150
+result=$("$FORTSH_BIN" -c 'printf "%05d\n" 42' 2>&1)
151
+if [ "$result" = "00042" ]; then
152
+    pass "printf %05d zero padding"
153
+else
154
+    fail "printf %05d zero padding" "00042" "$result"
155
+fi
156
+
157
+result=$("$FORTSH_BIN" -c 'printf "%-5d|\n" 42' 2>&1)
158
+if [ "$result" = "42   |" ]; then
159
+    pass "printf %-5d left-align"
160
+else
161
+    fail "printf %-5d left-align" "42   |" "$result"
162
+fi
163
+
164
+result=$("$FORTSH_BIN" -c 'printf "%+d\n" 42' 2>&1)
165
+if [ "$result" = "+42" ]; then
166
+    pass "printf %+d explicit plus sign"
167
+else
168
+    fail "printf %+d explicit plus sign" "+42" "$result"
169
+fi
170
+
171
+# =====================================
172
+section "360. PRINTF OCTAL AND HEX FORMATS %o %x %X"
173
+# =====================================
174
+
175
+result=$("$FORTSH_BIN" -c 'printf "%o\n" 8' 2>&1)
176
+if [ "$result" = "10" ]; then
177
+    pass "printf %o octal format"
178
+else
179
+    fail "printf %o octal format" "10" "$result"
180
+fi
181
+
182
+result=$("$FORTSH_BIN" -c 'printf "%x\n" 255' 2>&1)
183
+if [ "$result" = "ff" ]; then
184
+    pass "printf %x lowercase hex"
185
+else
186
+    fail "printf %x lowercase hex" "ff" "$result"
187
+fi
188
+
189
+result=$("$FORTSH_BIN" -c 'printf "%X\n" 255' 2>&1)
190
+if [ "$result" = "FF" ]; then
191
+    pass "printf %X uppercase hex"
192
+else
193
+    fail "printf %X uppercase hex" "FF" "$result"
194
+fi
195
+
196
+result=$("$FORTSH_BIN" -c 'printf "%#x\n" 255' 2>&1)
197
+if [ "$result" = "0xff" ]; then
198
+    pass "printf %#x alternate form"
199
+else
200
+    fail "printf %#x alternate form" "0xff" "$result"
201
+fi
202
+
203
+result=$("$FORTSH_BIN" -c 'printf "%#o\n" 8' 2>&1)
204
+if [ "$result" = "010" ]; then
205
+    pass "printf %#o alternate octal form"
206
+else
207
+    fail "printf %#o alternate octal form" "010" "$result"
208
+fi
209
+
210
+# =====================================
211
+section "361. PRINTF CHARACTER FORMAT %c"
212
+# =====================================
213
+
214
+result=$("$FORTSH_BIN" -c 'printf "%c\n" A' 2>&1)
215
+if [ "$result" = "A" ]; then
216
+    pass "printf %c single character"
217
+else
218
+    fail "printf %c single character" "A" "$result"
219
+fi
220
+
221
+result=$("$FORTSH_BIN" -c 'printf "%c\n" "hello"' 2>&1)
222
+if [ "$result" = "h" ]; then
223
+    pass "printf %c first char of string"
224
+else
225
+    fail "printf %c first char of string" "h" "$result"
226
+fi
227
+
228
+result=$("$FORTSH_BIN" -c 'printf "%c%c%c\n" a b c' 2>&1)
229
+if [ "$result" = "abc" ]; then
230
+    pass "printf %c multiple chars"
231
+else
232
+    fail "printf %c multiple chars" "abc" "$result"
233
+fi
234
+
235
+# =====================================
236
+section "362. PRINTF ESCAPE SEQUENCES"
237
+# =====================================
238
+
239
+result=$("$FORTSH_BIN" -c 'printf "hello\nworld\n"' 2>&1)
240
+expected=$(printf "hello\nworld")
241
+if [ "$result" = "$expected" ]; then
242
+    pass "printf \\n newline"
243
+else
244
+    fail "printf \\n newline" "$expected" "$result"
245
+fi
246
+
247
+result=$("$FORTSH_BIN" -c 'printf "a\tb\n"' 2>&1)
248
+expected=$(printf "a\tb")
249
+if [ "$result" = "$expected" ]; then
250
+    pass "printf \\t tab"
251
+else
252
+    fail "printf \\t tab" "$expected" "$result"
253
+fi
254
+
255
+result=$("$FORTSH_BIN" -c 'printf "back\\\\slash\n"' 2>&1)
256
+if [ "$result" = 'back\slash' ]; then
257
+    pass "printf \\\\ literal backslash"
258
+else
259
+    fail "printf \\\\ literal backslash" 'back\slash' "$result"
260
+fi
261
+
262
+result=$("$FORTSH_BIN" -c 'printf "100%%\n"' 2>&1)
263
+if [ "$result" = "100%" ]; then
264
+    pass "printf %% literal percent"
265
+else
266
+    fail "printf %% literal percent" "100%" "$result"
267
+fi
268
+
269
+result=$("$FORTSH_BIN" -c 'printf "\101\n"' 2>&1)
270
+if [ "$result" = "A" ]; then
271
+    pass "printf \\NNN octal escape"
272
+else
273
+    fail "printf \\NNN octal escape" "A" "$result"
274
+fi
275
+
276
+# =====================================
277
+section "363. PRINTF %b ESCAPE INTERPRETATION"
278
+# =====================================
279
+
280
+result=$("$FORTSH_BIN" -c 'printf "%b\n" "hello\nworld"' 2>&1)
281
+expected=$(printf "hello\nworld")
282
+if [ "$result" = "$expected" ]; then
283
+    pass "printf %b interprets backslash escapes"
284
+else
285
+    fail "printf %b interprets backslash escapes" "(newline)" "$result"
286
+fi
287
+
288
+result=$("$FORTSH_BIN" -c 'printf "%b\n" "tab\there"' 2>&1)
289
+expected=$(printf "tab\there")
290
+if [ "$result" = "$expected" ]; then
291
+    pass "printf %b interprets \\t"
292
+else
293
+    fail "printf %b interprets \\t" "(tab)" "$result"
294
+fi
295
+
296
+# =====================================
297
+section "364. PRINTF FORMAT REUSE"
298
+# =====================================
299
+
300
+result=$("$FORTSH_BIN" -c 'printf "%s\n" one two three' 2>&1)
301
+expected=$(printf "one\ntwo\nthree")
302
+if [ "$result" = "$expected" ]; then
303
+    pass "printf format reused for extra args"
304
+else
305
+    fail "printf format reused for extra args" "$expected" "$result"
306
+fi
307
+
308
+result=$("$FORTSH_BIN" -c 'printf "%d " 1 2 3 4 5; printf "\n"' 2>&1)
309
+if [ "$result" = "1 2 3 4 5 " ]; then
310
+    pass "printf %d reused for multiple integers"
311
+else
312
+    fail "printf %d reused for multiple integers" "1 2 3 4 5 " "$result"
313
+fi
314
+
315
+# =====================================
316
+section "365. PRINTF WITH VARIABLES"
317
+# =====================================
318
+
319
+result=$("$FORTSH_BIN" -c 'x="hello"; printf "%s\n" "$x"' 2>&1)
320
+if [ "$result" = "hello" ]; then
321
+    pass "printf with variable argument"
322
+else
323
+    fail "printf with variable argument" "hello" "$result"
324
+fi
325
+
326
+result=$("$FORTSH_BIN" -c 'n=42; printf "Value: %d\n" "$n"' 2>&1)
327
+if [ "$result" = "Value: 42" ]; then
328
+    pass "printf integer from variable"
329
+else
330
+    fail "printf integer from variable" "Value: 42" "$result"
331
+fi
332
+
333
+result=$("$FORTSH_BIN" -c 'fmt="%s: %d\n"; printf "$fmt" name 42' 2>&1)
334
+if [ "$result" = "name: 42" ]; then
335
+    pass "printf format from variable"
336
+else
337
+    fail "printf format from variable" "name: 42" "$result"
338
+fi
339
+
340
+# =====================================
341
+section "366. PRINTF DYNAMIC WIDTH AND PRECISION"
342
+# =====================================
343
+
344
+result=$("$FORTSH_BIN" -c 'printf "%*s\n" 10 hi' 2>&1)
345
+if [ "$result" = "        hi" ]; then
346
+    pass "printf %*s dynamic width"
347
+else
348
+    fail "printf %*s dynamic width" "        hi" "$result"
349
+fi
350
+
351
+result=$("$FORTSH_BIN" -c 'printf "%.*s\n" 3 hello' 2>&1)
352
+if [ "$result" = "hel" ]; then
353
+    pass "printf %.*s dynamic precision"
354
+else
355
+    fail "printf %.*s dynamic precision" "hel" "$result"
356
+fi
357
+
358
+result=$("$FORTSH_BIN" -c 'printf "%*.*s\n" 10 3 hello' 2>&1)
359
+if [ "$result" = "       hel" ]; then
360
+    pass "printf %*.*s dynamic width and precision"
361
+else
362
+    fail "printf %*.*s dynamic width and precision" "       hel" "$result"
363
+fi
364
+
365
+# =====================================
366
+section "367. PRINTF RETURN VALUE"
367
+# =====================================
368
+
369
+result=$("$FORTSH_BIN" -c 'printf "%s" "test"; echo $?' 2>&1)
370
+if echo "$result" | grep -q "0"; then
371
+    pass "printf returns 0 on success"
372
+else
373
+    fail "printf returns 0 on success" "0" "$result"
374
+fi
375
+
376
+# =====================================
377
+section "368. PRINTF EDGE CASES"
378
+# =====================================
379
+
380
+result=$("$FORTSH_BIN" -c 'printf "%d\n" 0' 2>&1)
381
+if [ "$result" = "0" ]; then
382
+    pass "printf %d zero"
383
+else
384
+    fail "printf %d zero" "0" "$result"
385
+fi
386
+
387
+result=$("$FORTSH_BIN" -c 'printf "%s\n" ""' 2>&1)
388
+if [ "$result" = "" ]; then
389
+    pass "printf empty argument"
390
+else
391
+    fail "printf empty argument" "(empty)" "$result"
392
+fi
393
+
394
+result=$("$FORTSH_BIN" -c 'printf "no format"' 2>&1)
395
+if [ "$result" = "no format" ]; then
396
+    pass "printf literal string no format"
397
+else
398
+    fail "printf literal string no format" "no format" "$result"
399
+fi
400
+
401
+result=$("$FORTSH_BIN" -c 'printf ""' 2>&1)
402
+if [ "$result" = "" ]; then
403
+    pass "printf empty format string"
404
+else
405
+    fail "printf empty format string" "(empty)" "$result"
406
+fi
407
+
408
+# =====================================
409
+# Summary
410
+# =====================================
411
+printf "\n"
412
+printf "${BLUE}==========================================\n"
413
+printf "POSIX printf Builtin Test Summary\n"
414
+printf "==========================================${NC}\n"
415
+printf "Passed:  ${GREEN}%d${NC}\n" "$PASSED"
416
+printf "Failed:  ${RED}%d${NC}\n" "$FAILED"
417
+printf "Skipped: ${YELLOW}%d${NC}\n" "$SKIPPED"
418
+printf "Total:   %d\n" "$((PASSED + FAILED + SKIPPED))"
419
+
420
+if [ -n "$FAILED_TESTS_LIST" ]; then
421
+    printf "\n${RED}Failed tests:${NC}\n"
422
+    printf "%b" "$FAILED_TESTS_LIST"
423
+fi
424
+
425
+if [ "$FAILED" -gt 0 ]; then
426
+    exit 1
427
+fi
428
+exit 0
tests/run_all_tests.shmodified
@@ -119,6 +119,8 @@ posix_compliance_gaps.sh
119119
 posix_compliance_jobcontrol.sh
120120
 posix_compliance_charclass.sh
121121
 posix_compliance_special.sh
122
+posix_compliance_printf.sh
123
+posix_compliance_filetest.sh
122124
 "
123125
 
124126
 POSIX_SLOW_TESTS="