Bash · 20877 bytes Raw Blame History
1 #!/bin/sh
2 # =====================================
3 # POSIX Compliance Here-Document and Expansion Test Suite for fortsh
4 # =====================================
5 # Tests here-documents and parameter expansion per IEEE Std 1003.1-2017
6 # Section: Shell Command Language - Here-Documents, Parameter Expansion
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-heredoc]"
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 "396. BASIC HERE-DOCUMENT"
74 # =====================================
75
76 result=$("$FORTSH_BIN" -c 'cat <<EOF
77 hello world
78 EOF' 2>&1)
79 if [ "$result" = "hello world" ]; then
80 pass "Basic here-document"
81 else
82 fail "Basic here-document" "hello world" "$result"
83 fi
84
85 result=$("$FORTSH_BIN" -c 'cat <<END
86 line one
87 line two
88 END' 2>&1)
89 expected=$(printf "line one\nline two")
90 if [ "$result" = "$expected" ]; then
91 pass "Here-document multiple lines"
92 else
93 fail "Here-document multiple lines" "$expected" "$result"
94 fi
95
96 result=$("$FORTSH_BIN" -c 'x=world; cat <<EOF
97 hello $x
98 EOF' 2>&1)
99 if [ "$result" = "hello world" ]; then
100 pass "Here-document with variable expansion"
101 else
102 fail "Here-document with variable expansion" "hello world" "$result"
103 fi
104
105 result=$("$FORTSH_BIN" -c 'cat <<EOF
106 result: $(echo test)
107 EOF' 2>&1)
108 if [ "$result" = "result: test" ]; then
109 pass "Here-document with command substitution"
110 else
111 fail "Here-document with command substitution" "result: test" "$result"
112 fi
113
114 # =====================================
115 section "397. QUOTED HERE-DOCUMENT DELIMITER"
116 # =====================================
117
118 result=$("$FORTSH_BIN" -c 'x=world; cat <<"EOF"
119 hello $x
120 EOF' 2>&1)
121 if [ "$result" = 'hello $x' ]; then
122 pass "Quoted delimiter prevents expansion"
123 else
124 fail "Quoted delimiter prevents expansion" 'hello $x' "$result"
125 fi
126
127 result=$("$FORTSH_BIN" -c "cat <<'END'
128 test \$(echo foo)
129 END" 2>&1)
130 if [ "$result" = 'test $(echo foo)' ]; then
131 pass "Single-quoted delimiter prevents command sub"
132 else
133 fail "Single-quoted delimiter prevents command sub" 'test $(echo foo)' "$result"
134 fi
135
136 # =====================================
137 section "398. HERE-DOCUMENT WITH TAB STRIPPING (<<-)"
138 # =====================================
139
140 result=$("$FORTSH_BIN" -c ' cat <<-EOF
141 hello
142 world
143 EOF' 2>&1)
144 expected=$(printf "hello\nworld")
145 if [ "$result" = "$expected" ]; then
146 pass "<<- strips leading tabs"
147 else
148 fail "<<- strips leading tabs" "$expected" "$result"
149 fi
150
151 result=$("$FORTSH_BIN" -c 'cat <<-END
152 indented
153 END' 2>&1)
154 if [ "$result" = "indented" ]; then
155 pass "<<- strips multiple tabs"
156 else
157 fail "<<- strips multiple tabs" "indented" "$result"
158 fi
159
160 # =====================================
161 section "399. HERE-DOCUMENT TO DIFFERENT COMMANDS"
162 # =====================================
163
164 result=$("$FORTSH_BIN" -c 'wc -l <<EOF
165 one
166 two
167 three
168 EOF' 2>&1)
169 if echo "$result" | grep -q "3"; then
170 pass "Here-document to wc -l"
171 else
172 fail "Here-document to wc -l" "3" "$result"
173 fi
174
175 # Note: read with heredoc can hang if not implemented - use timeout
176 # Portable: macOS lacks GNU timeout
177 if command -v timeout >/dev/null 2>&1; then
178 _timeout() { timeout "$@"; }
179 elif command -v gtimeout >/dev/null 2>&1; then
180 _timeout() { gtimeout "$@"; }
181 else
182 _timeout() {
183 _to_secs="$1"; shift
184 _to_tmp=$(mktemp /tmp/fortsh_timeout.XXXXXX)
185 ( "$@" ) > "$_to_tmp" 2>&1 &
186 _to_pid=$!
187 ( sleep "$_to_secs"; kill "$_to_pid" 2>/dev/null ) &
188 _to_wd=$!
189 wait "$_to_pid" 2>/dev/null
190 _to_rc=$?
191 kill "$_to_wd" 2>/dev/null
192 wait "$_to_wd" 2>/dev/null
193 cat "$_to_tmp"
194 rm -f "$_to_tmp"
195 return $_to_rc
196 }
197 fi
198 result=$(_timeout 2 "$FORTSH_BIN" -c 'read x <<EOF
199 test input
200 EOF
201 echo "$x"' 2>&1)
202 exit_code=$?
203 if [ "$result" = "test input" ]; then
204 pass "Here-document to read"
205 elif [ $exit_code -eq 124 ]; then
206 fail "Here-document to read" "test input" "(timeout - hangs)"
207 else
208 fail "Here-document to read" "test input" "$result"
209 fi
210
211 # =====================================
212 section "400. PARAMETER EXPANSION ${var:-default}"
213 # =====================================
214
215 result=$("$FORTSH_BIN" -c 'unset x; echo ${x:-default}' 2>&1)
216 if [ "$result" = "default" ]; then
217 pass "\${var:-default} for unset variable"
218 else
219 fail "\${var:-default} for unset variable" "default" "$result"
220 fi
221
222 result=$("$FORTSH_BIN" -c 'x=""; echo ${x:-default}' 2>&1)
223 if [ "$result" = "default" ]; then
224 pass "\${var:-default} for empty variable"
225 else
226 fail "\${var:-default} for empty variable" "default" "$result"
227 fi
228
229 result=$("$FORTSH_BIN" -c 'x=value; echo ${x:-default}' 2>&1)
230 if [ "$result" = "value" ]; then
231 pass "\${var:-default} for set variable"
232 else
233 fail "\${var:-default} for set variable" "value" "$result"
234 fi
235
236 result=$("$FORTSH_BIN" -c 'unset x; echo ${x-default}' 2>&1)
237 if [ "$result" = "default" ]; then
238 pass "\${var-default} for unset (no colon)"
239 else
240 fail "\${var-default} for unset (no colon)" "default" "$result"
241 fi
242
243 result=$("$FORTSH_BIN" -c 'x=""; echo ${x-default}' 2>&1)
244 if [ "$result" = "" ]; then
245 pass "\${var-default} for empty (no colon)"
246 else
247 fail "\${var-default} for empty (no colon)" "(empty)" "$result"
248 fi
249
250 # =====================================
251 section "401. PARAMETER EXPANSION ${var:+alternate}"
252 # =====================================
253
254 result=$("$FORTSH_BIN" -c 'x=value; echo ${x:+alternate}' 2>&1)
255 if [ "$result" = "alternate" ]; then
256 pass "\${var:+alternate} for set variable"
257 else
258 fail "\${var:+alternate} for set variable" "alternate" "$result"
259 fi
260
261 result=$("$FORTSH_BIN" -c 'unset x; echo ${x:+alternate}' 2>&1)
262 if [ "$result" = "" ]; then
263 pass "\${var:+alternate} for unset variable"
264 else
265 fail "\${var:+alternate} for unset variable" "(empty)" "$result"
266 fi
267
268 result=$("$FORTSH_BIN" -c 'x=""; echo ${x:+alternate}' 2>&1)
269 if [ "$result" = "" ]; then
270 pass "\${var:+alternate} for empty variable"
271 else
272 fail "\${var:+alternate} for empty variable" "(empty)" "$result"
273 fi
274
275 # =====================================
276 section "402. PARAMETER EXPANSION ${var:=assign}"
277 # =====================================
278
279 result=$("$FORTSH_BIN" -c 'unset x; echo ${x:=assigned}; echo $x' 2>&1)
280 expected=$(printf "assigned\nassigned")
281 if [ "$result" = "$expected" ]; then
282 pass "\${var:=value} assigns when unset"
283 else
284 fail "\${var:=value} assigns when unset" "$expected" "$result"
285 fi
286
287 result=$("$FORTSH_BIN" -c 'x=""; echo ${x:=assigned}; echo $x' 2>&1)
288 expected=$(printf "assigned\nassigned")
289 if [ "$result" = "$expected" ]; then
290 pass "\${var:=value} assigns when empty"
291 else
292 fail "\${var:=value} assigns when empty" "$expected" "$result"
293 fi
294
295 result=$("$FORTSH_BIN" -c 'x=original; echo ${x:=assigned}; echo $x' 2>&1)
296 expected=$(printf "original\noriginal")
297 if [ "$result" = "$expected" ]; then
298 pass "\${var:=value} keeps original when set"
299 else
300 fail "\${var:=value} keeps original when set" "$expected" "$result"
301 fi
302
303 # =====================================
304 section "403. PARAMETER EXPANSION ${var:?error}"
305 # =====================================
306
307 result=$("$FORTSH_BIN" -c 'x=value; echo ${x:?error message}' 2>&1)
308 if [ "$result" = "value" ]; then
309 pass "\${var:?error} returns value when set"
310 else
311 fail "\${var:?error} returns value when set" "value" "$result"
312 fi
313
314 result=$("$FORTSH_BIN" -c 'unset x; echo ${x:?custom error}' 2>&1)
315 if echo "$result" | grep -qi "error\|custom"; then
316 pass "\${var:?error} shows error when unset"
317 else
318 fail "\${var:?error} shows error when unset" "error message" "$result"
319 fi
320
321 # =====================================
322 section "404. PARAMETER EXPANSION ${#var}"
323 # =====================================
324
325 result=$("$FORTSH_BIN" -c 'x=hello; echo ${#x}' 2>&1)
326 if [ "$result" = "5" ]; then
327 pass "\${#var} string length"
328 else
329 fail "\${#var} string length" "5" "$result"
330 fi
331
332 result=$("$FORTSH_BIN" -c 'x=""; echo ${#x}' 2>&1)
333 if [ "$result" = "0" ]; then
334 pass "\${#var} empty string length"
335 else
336 fail "\${#var} empty string length" "0" "$result"
337 fi
338
339 result=$("$FORTSH_BIN" -c 'x="hello world"; echo ${#x}' 2>&1)
340 if [ "$result" = "11" ]; then
341 pass "\${#var} string with space"
342 else
343 fail "\${#var} string with space" "11" "$result"
344 fi
345
346 # =====================================
347 section "405. PARAMETER EXPANSION ${var%pattern}"
348 # =====================================
349
350 result=$("$FORTSH_BIN" -c 'x="file.txt"; echo ${x%.txt}' 2>&1)
351 if [ "$result" = "file" ]; then
352 pass "\${var%pattern} removes shortest suffix"
353 else
354 fail "\${var%pattern} removes shortest suffix" "file" "$result"
355 fi
356
357 result=$("$FORTSH_BIN" -c 'x="file.tar.gz"; echo ${x%.*}' 2>&1)
358 if [ "$result" = "file.tar" ]; then
359 pass "\${var%.*} removes extension"
360 else
361 fail "\${var%.*} removes extension" "file.tar" "$result"
362 fi
363
364 result=$("$FORTSH_BIN" -c 'x="file.tar.gz"; echo ${x%%.*}' 2>&1)
365 if [ "$result" = "file" ]; then
366 pass "\${var%%.*} removes all extensions"
367 else
368 fail "\${var%%.*} removes all extensions" "file" "$result"
369 fi
370
371 # =====================================
372 section "406. PARAMETER EXPANSION ${var#pattern}"
373 # =====================================
374
375 result=$("$FORTSH_BIN" -c 'x="/path/to/file"; echo ${x#*/}' 2>&1)
376 if [ "$result" = "path/to/file" ]; then
377 pass "\${var#*/} removes shortest prefix"
378 else
379 fail "\${var#*/} removes shortest prefix" "path/to/file" "$result"
380 fi
381
382 result=$("$FORTSH_BIN" -c 'x="/path/to/file"; echo ${x##*/}' 2>&1)
383 if [ "$result" = "file" ]; then
384 pass "\${var##*/} basename extraction"
385 else
386 fail "\${var##*/} basename extraction" "file" "$result"
387 fi
388
389 result=$("$FORTSH_BIN" -c 'x="prefix_name"; echo ${x#prefix_}' 2>&1)
390 if [ "$result" = "name" ]; then
391 pass "\${var#prefix} removes literal prefix"
392 else
393 fail "\${var#prefix} removes literal prefix" "name" "$result"
394 fi
395
396 # =====================================
397 section "407. BACKTICK COMMAND SUBSTITUTION"
398 # =====================================
399
400 result=$("$FORTSH_BIN" -c 'echo `echo hello`' 2>&1)
401 if [ "$result" = "hello" ]; then
402 pass "Basic backtick substitution"
403 else
404 fail "Basic backtick substitution" "hello" "$result"
405 fi
406
407 result=$("$FORTSH_BIN" -c 'x=`expr 2 + 3`; echo $x' 2>&1)
408 if [ "$result" = "5" ]; then
409 pass "Backtick with expr"
410 else
411 fail "Backtick with expr" "5" "$result"
412 fi
413
414 result=$("$FORTSH_BIN" -c 'echo `echo \`echo nested\``' 2>&1)
415 if [ "$result" = "nested" ]; then
416 pass "Nested backtick substitution"
417 else
418 fail "Nested backtick substitution" "nested" "$result"
419 fi
420
421 # =====================================
422 section "408. COMMAND SUBSTITUTION EDGE CASES"
423 # =====================================
424
425 result=$("$FORTSH_BIN" -c 'echo "$(echo "inner quotes")"' 2>&1)
426 if [ "$result" = "inner quotes" ]; then
427 pass "\$(...) with inner quotes"
428 else
429 fail "\$(...) with inner quotes" "inner quotes" "$result"
430 fi
431
432 result=$("$FORTSH_BIN" -c 'echo $(echo $(echo nested))' 2>&1)
433 if [ "$result" = "nested" ]; then
434 pass "Nested \$(...) substitution"
435 else
436 fail "Nested \$(...) substitution" "nested" "$result"
437 fi
438
439 result=$("$FORTSH_BIN" -c 'x=$(cat <<EOF
440 multi
441 line
442 EOF
443 ); echo "$x"' 2>&1)
444 expected=$(printf "multi\nline")
445 if [ "$result" = "$expected" ]; then
446 pass "\$(...) with here-document inside"
447 else
448 fail "\$(...) with here-document inside" "$expected" "$result"
449 fi
450
451 # =====================================
452 section "409. ARITHMETIC EXPANSION"
453 # =====================================
454
455 result=$("$FORTSH_BIN" -c 'echo $((2 + 3))' 2>&1)
456 if [ "$result" = "5" ]; then
457 pass "\$((...)) addition"
458 else
459 fail "\$((...)) addition" "5" "$result"
460 fi
461
462 result=$("$FORTSH_BIN" -c 'echo $((10 - 3))' 2>&1)
463 if [ "$result" = "7" ]; then
464 pass "\$((...)) subtraction"
465 else
466 fail "\$((...)) subtraction" "7" "$result"
467 fi
468
469 result=$("$FORTSH_BIN" -c 'echo $((4 * 5))' 2>&1)
470 if [ "$result" = "20" ]; then
471 pass "\$((...)) multiplication"
472 else
473 fail "\$((...)) multiplication" "20" "$result"
474 fi
475
476 result=$("$FORTSH_BIN" -c 'echo $((20 / 4))' 2>&1)
477 if [ "$result" = "5" ]; then
478 pass "\$((...)) division"
479 else
480 fail "\$((...)) division" "5" "$result"
481 fi
482
483 result=$("$FORTSH_BIN" -c 'echo $((17 % 5))' 2>&1)
484 if [ "$result" = "2" ]; then
485 pass "\$((...)) modulo"
486 else
487 fail "\$((...)) modulo" "2" "$result"
488 fi
489
490 result=$("$FORTSH_BIN" -c 'x=5; echo $((x * 2))' 2>&1)
491 if [ "$result" = "10" ]; then
492 pass "\$((...)) with variable (no \$)"
493 else
494 fail "\$((...)) with variable (no \$)" "10" "$result"
495 fi
496
497 result=$("$FORTSH_BIN" -c 'x=5; echo $(($x * 2))' 2>&1)
498 if [ "$result" = "10" ]; then
499 pass "\$((...)) with \$variable"
500 else
501 fail "\$((...)) with \$variable" "10" "$result"
502 fi
503
504 result=$("$FORTSH_BIN" -c 'echo $(( (2 + 3) * 4 ))' 2>&1)
505 if [ "$result" = "20" ]; then
506 pass "\$((...)) with parentheses"
507 else
508 fail "\$((...)) with parentheses" "20" "$result"
509 fi
510
511 result=$("$FORTSH_BIN" -c 'echo $((-5 + 3))' 2>&1)
512 if [ "$result" = "-2" ]; then
513 pass "\$((...)) negative numbers"
514 else
515 fail "\$((...)) negative numbers" "-2" "$result"
516 fi
517
518 result=$("$FORTSH_BIN" -c 'echo $((5 > 3))' 2>&1)
519 if [ "$result" = "1" ]; then
520 pass "\$((...)) greater than comparison"
521 else
522 fail "\$((...)) greater than comparison" "1" "$result"
523 fi
524
525 result=$("$FORTSH_BIN" -c 'echo $((3 > 5))' 2>&1)
526 if [ "$result" = "0" ]; then
527 pass "\$((...)) greater than false"
528 else
529 fail "\$((...)) greater than false" "0" "$result"
530 fi
531
532 result=$("$FORTSH_BIN" -c 'echo $((5 < 10))' 2>&1)
533 if [ "$result" = "1" ]; then
534 pass "\$((...)) less than comparison"
535 else
536 fail "\$((...)) less than comparison" "1" "$result"
537 fi
538
539 result=$("$FORTSH_BIN" -c 'echo $((5 == 5))' 2>&1)
540 if [ "$result" = "1" ]; then
541 pass "\$((...)) equality"
542 else
543 fail "\$((...)) equality" "1" "$result"
544 fi
545
546 result=$("$FORTSH_BIN" -c 'echo $((5 != 3))' 2>&1)
547 if [ "$result" = "1" ]; then
548 pass "\$((...)) inequality"
549 else
550 fail "\$((...)) inequality" "1" "$result"
551 fi
552
553 result=$("$FORTSH_BIN" -c 'echo $((5 >= 5))' 2>&1)
554 if [ "$result" = "1" ]; then
555 pass "\$((...)) greater or equal"
556 else
557 fail "\$((...)) greater or equal" "1" "$result"
558 fi
559
560 result=$("$FORTSH_BIN" -c 'echo $((3 <= 5))' 2>&1)
561 if [ "$result" = "1" ]; then
562 pass "\$((...)) less or equal"
563 else
564 fail "\$((...)) less or equal" "1" "$result"
565 fi
566
567 result=$("$FORTSH_BIN" -c 'echo $((1 && 1))' 2>&1)
568 if [ "$result" = "1" ]; then
569 pass "\$((...)) logical AND"
570 else
571 fail "\$((...)) logical AND" "1" "$result"
572 fi
573
574 result=$("$FORTSH_BIN" -c 'echo $((1 && 0))' 2>&1)
575 if [ "$result" = "0" ]; then
576 pass "\$((...)) logical AND false"
577 else
578 fail "\$((...)) logical AND false" "0" "$result"
579 fi
580
581 result=$("$FORTSH_BIN" -c 'echo $((0 || 1))' 2>&1)
582 if [ "$result" = "1" ]; then
583 pass "\$((...)) logical OR"
584 else
585 fail "\$((...)) logical OR" "1" "$result"
586 fi
587
588 result=$("$FORTSH_BIN" -c 'echo $((!0))' 2>&1)
589 if [ "$result" = "1" ]; then
590 pass "\$((...)) logical NOT"
591 else
592 fail "\$((...)) logical NOT" "1" "$result"
593 fi
594
595 result=$("$FORTSH_BIN" -c 'echo $((5 & 3))' 2>&1)
596 if [ "$result" = "1" ]; then
597 pass "\$((...)) bitwise AND"
598 else
599 fail "\$((...)) bitwise AND" "1" "$result"
600 fi
601
602 result=$("$FORTSH_BIN" -c 'echo $((5 | 3))' 2>&1)
603 if [ "$result" = "7" ]; then
604 pass "\$((...)) bitwise OR"
605 else
606 fail "\$((...)) bitwise OR" "7" "$result"
607 fi
608
609 result=$("$FORTSH_BIN" -c 'echo $((5 ^ 3))' 2>&1)
610 if [ "$result" = "6" ]; then
611 pass "\$((...)) bitwise XOR"
612 else
613 fail "\$((...)) bitwise XOR" "6" "$result"
614 fi
615
616 result=$("$FORTSH_BIN" -c 'echo $((1 << 4))' 2>&1)
617 if [ "$result" = "16" ]; then
618 pass "\$((...)) left shift"
619 else
620 fail "\$((...)) left shift" "16" "$result"
621 fi
622
623 result=$("$FORTSH_BIN" -c 'echo $((16 >> 2))' 2>&1)
624 if [ "$result" = "4" ]; then
625 pass "\$((...)) right shift"
626 else
627 fail "\$((...)) right shift" "4" "$result"
628 fi
629
630 result=$("$FORTSH_BIN" -c 'echo $((5 > 3 ? 10 : 20))' 2>&1)
631 if [ "$result" = "10" ]; then
632 pass "\$((...)) ternary true"
633 else
634 fail "\$((...)) ternary true" "10" "$result"
635 fi
636
637 result=$("$FORTSH_BIN" -c 'echo $((5 < 3 ? 10 : 20))' 2>&1)
638 if [ "$result" = "20" ]; then
639 pass "\$((...)) ternary false"
640 else
641 fail "\$((...)) ternary false" "20" "$result"
642 fi
643
644 result=$("$FORTSH_BIN" -c 'x=5; echo $((x += 3)); echo $x' 2>&1)
645 expected=$(printf "8\n8")
646 if [ "$result" = "$expected" ]; then
647 pass "\$((...)) += assignment"
648 else
649 fail "\$((...)) += assignment" "$expected" "$result"
650 fi
651
652 result=$("$FORTSH_BIN" -c 'x=10; echo $((x -= 3)); echo $x' 2>&1)
653 expected=$(printf "7\n7")
654 if [ "$result" = "$expected" ]; then
655 pass "\$((...)) -= assignment"
656 else
657 fail "\$((...)) -= assignment" "$expected" "$result"
658 fi
659
660 result=$("$FORTSH_BIN" -c 'x=5; echo $((x *= 3))' 2>&1)
661 if [ "$result" = "15" ]; then
662 pass "\$((...)) *= assignment"
663 else
664 fail "\$((...)) *= assignment" "15" "$result"
665 fi
666
667 result=$("$FORTSH_BIN" -c 'x=5; echo $((++x)); echo $x' 2>&1)
668 expected=$(printf "6\n6")
669 if [ "$result" = "$expected" ]; then
670 pass "\$((...)) pre-increment"
671 else
672 fail "\$((...)) pre-increment" "$expected" "$result"
673 fi
674
675 result=$("$FORTSH_BIN" -c 'x=5; echo $((x++)); echo $x' 2>&1)
676 expected=$(printf "5\n6")
677 if [ "$result" = "$expected" ]; then
678 pass "\$((...)) post-increment"
679 else
680 fail "\$((...)) post-increment" "$expected" "$result"
681 fi
682
683 result=$("$FORTSH_BIN" -c 'x=5; echo $((--x)); echo $x' 2>&1)
684 expected=$(printf "4\n4")
685 if [ "$result" = "$expected" ]; then
686 pass "\$((...)) pre-decrement"
687 else
688 fail "\$((...)) pre-decrement" "$expected" "$result"
689 fi
690
691 result=$("$FORTSH_BIN" -c 'x=5; echo $((x--)); echo $x' 2>&1)
692 expected=$(printf "5\n4")
693 if [ "$result" = "$expected" ]; then
694 pass "\$((...)) post-decrement"
695 else
696 fail "\$((...)) post-decrement" "$expected" "$result"
697 fi
698
699 result=$("$FORTSH_BIN" -c 'echo $(( 2 + 3 * 4 ))' 2>&1)
700 if [ "$result" = "14" ]; then
701 pass "\$((...)) operator precedence"
702 else
703 fail "\$((...)) operator precedence" "14" "$result"
704 fi
705
706 result=$("$FORTSH_BIN" -c 'a=2; b=3; echo $(( a * b + a ))' 2>&1)
707 if [ "$result" = "8" ]; then
708 pass "\$((...)) multiple variables"
709 else
710 fail "\$((...)) multiple variables" "8" "$result"
711 fi
712
713 # =====================================
714 section "410. TILDE EXPANSION"
715 # =====================================
716
717 result=$("$FORTSH_BIN" -c 'echo ~' 2>&1)
718 if [ "$result" = "$HOME" ]; then
719 pass "~ expands to \$HOME"
720 else
721 fail "~ expands to \$HOME" "$HOME" "$result"
722 fi
723
724 result=$("$FORTSH_BIN" -c 'echo ~/test' 2>&1)
725 if [ "$result" = "$HOME/test" ]; then
726 pass "~/path expands correctly"
727 else
728 fail "~/path expands correctly" "$HOME/test" "$result"
729 fi
730
731 result=$("$FORTSH_BIN" -c 'x=~; echo $x' 2>&1)
732 if [ "$result" = "$HOME" ]; then
733 pass "~ in assignment expands"
734 else
735 fail "~ in assignment expands" "$HOME" "$result"
736 fi
737
738 # =====================================
739 # Summary
740 # =====================================
741 printf "\n"
742 printf "${BLUE}==========================================\n"
743 printf "POSIX Here-Document and Expansion Summary\n"
744 printf "==========================================${NC}\n"
745 printf "Passed: ${GREEN}%d${NC}\n" "$PASSED"
746 printf "Failed: ${RED}%d${NC}\n" "$FAILED"
747 printf "Skipped: ${YELLOW}%d${NC}\n" "$SKIPPED"
748 printf "Total: %d\n" "$((PASSED + FAILED + SKIPPED))"
749
750 if [ -n "$FAILED_TESTS_LIST" ]; then
751 printf "\n${RED}Failed tests:${NC}\n"
752 printf "%b" "$FAILED_TESTS_LIST"
753 fi
754
755 if [ "$FAILED" -gt 0 ]; then
756 exit 1
757 fi
758 exit 0