tenseleyflow/bensch / 431107b

Browse files

extract interactive specs: prompt, stress, auto-generated POSIX

prompt_display.yaml -> suites/interactive/posix/
stress.yaml -> suites/interactive/stress/
7 posix_*_auto.yaml files -> suites/interactive/posix/

Verbatim copies. 4254 lines, ~692 test cases.

Source: fortsh/tests/interactive/test_specs/
Authored by espadonne
SHA
431107b293fa66eb21f391d7c28dea2545ab01fc
Parents
388c123
Tree
ef00967

9 changed files

StatusFile+-
A suites/interactive/posix/posix_advanced_auto.yaml 564 0
A suites/interactive/posix/posix_basic_auto.yaml 553 0
A suites/interactive/posix/posix_basic_sample.yaml 93 0
A suites/interactive/posix/posix_coverage_auto.yaml 574 0
A suites/interactive/posix/posix_extended_auto.yaml 701 0
A suites/interactive/posix/posix_gaps_auto.yaml 960 0
A suites/interactive/posix/posix_untested_auto.yaml 195 0
A suites/interactive/posix/prompt_display.yaml 325 0
A suites/interactive/stress/stress.yaml 289 0
suites/interactive/posix/posix_advanced_auto.yamladded
@@ -0,0 +1,564 @@
1
+metadata:
2
+  category: Advanced
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '51. BREAK AND CONTINUE IN LOOPS: break in for loop'
8
+  steps:
9
+  - send_line: for i in 1 2 3 4 5; do echo $i; if [ $i -eq 3 ]; then break; fi; done
10
+  expect_output: '3'
11
+  match_type: contains
12
+  auto_fixed: shell_execution
13
+- name: '51. BREAK AND CONTINUE IN LOOPS: continue in for loop'
14
+  steps:
15
+  - send_line: for i in 1 2 3 4 5; do if [ $i -eq 3 ]; then continue; fi; echo $i; done
16
+  expect_output: '4'
17
+  match_type: contains
18
+  auto_fixed: shell_execution
19
+- name: '51. BREAK AND CONTINUE IN LOOPS: break in while loop'
20
+  steps:
21
+  - send_line: i=0; while [ $i -lt 5 ]; do i=$((i+1)); echo $i; if [ $i -eq 3 ]; then break; fi; done
22
+  expect_output: '3'
23
+  match_type: contains
24
+  auto_fixed: shell_execution
25
+- name: '51. BREAK AND CONTINUE IN LOOPS: continue in while loop'
26
+  steps:
27
+  - send_line: i=0; while [ $i -lt 5 ]; do i=$((i+1)); if [ $i -eq 3 ]; then continue; fi; echo $i; done
28
+  expect_output: '5'
29
+  match_type: contains
30
+  auto_fixed: shell_execution
31
+- name: '51. BREAK AND CONTINUE IN LOOPS: break in until loop'
32
+  steps:
33
+  - send_line: i=0; until [ $i -ge 5 ]; do i=$((i+1)); echo $i; if [ $i -eq 3 ]; then break; fi; done
34
+  expect_output: '3'
35
+  match_type: contains
36
+  auto_fixed: shell_execution
37
+- name: '52. NESTED LOOPS WITH BREAK/CONTINUE: break inner loop'
38
+  steps:
39
+  - send_line: for i in 1 2; do for j in a b c; do echo $i$j; if [ $j = b ]; then break; fi; done; done
40
+  expect_output: '2b'
41
+  match_type: contains
42
+  auto_fixed: shell_execution
43
+- name: '52. NESTED LOOPS WITH BREAK/CONTINUE: break with level'
44
+  steps:
45
+  - send_line: for i in 1 2; do for j in a b; do echo $i$j; if [ $j = b ]; then break 2; fi; done; done
46
+  expect_output: '1b'
47
+  match_type: contains
48
+  auto_fixed: shell_execution
49
+- name: '52. NESTED LOOPS WITH BREAK/CONTINUE: continue outer loop'
50
+  steps:
51
+  - send_line: for i in 1 2 3; do for j in a b; do echo $i$j; if [ $j = a ]; then continue 2; fi; done; done
52
+  expect_output: '3a'
53
+  match_type: contains
54
+  auto_fixed: shell_execution
55
+- name: '53. EXEC BUILTIN: exec with redirect'
56
+  steps:
57
+  - send_line: exec 3>&1; echo test >&3; exec 3>&-; echo done
58
+  expect_output: done
59
+  match_type: contains
60
+- name: '53. EXEC BUILTIN: exec without command'
61
+  steps:
62
+  - send_line: exec 2>&1; pwd >/dev/null
63
+  expect_output: ''
64
+  match_type: exact
65
+- name: '54. COMMAND BUILTIN: command -v test'
66
+  steps:
67
+  - send_line: command -v test | grep -c test
68
+  expect_output: '[0-9]+'
69
+  match_type: regex
70
+- name: '54. COMMAND BUILTIN: command -v echo'
71
+  steps:
72
+  - send_line: command -v echo | grep -c echo
73
+  expect_output: '[0-9]+'
74
+  match_type: regex
75
+- name: '55. READ BUILTIN - THOROUGH TESTING: read single var'
76
+  steps:
77
+  - send_line: echo hello | read VAR 2>/dev/null || VAR=hello; echo $VAR
78
+  expect_output: ''
79
+  match_type: exact
80
+- name: '55. READ BUILTIN - THOROUGH TESTING: read multiple vars'
81
+  steps:
82
+  - send_line: echo one two three | { read A B C; echo $A $B $C; }
83
+  expect_output: one two three
84
+  match_type: contains
85
+  auto_fixed: shell_execution
86
+- name: '55. READ BUILTIN - THOROUGH TESTING: read with IFS'
87
+  steps:
88
+  - send_line: IFS=:; echo a:b:c | { read X Y Z; echo $X $Y $Z; }
89
+  expect_output: a b c
90
+  match_type: contains
91
+  auto_fixed: shell_execution
92
+- name: '55. READ BUILTIN - THOROUGH TESTING: read remaining to last'
93
+  steps:
94
+  - send_line: echo a b c d e | { read X Y Z; echo "$Z"; }
95
+  expect_output: c d e
96
+  match_type: contains
97
+  auto_fixed: shell_execution
98
+- name: '56. FILE DESCRIPTOR DUPLICATION: dup stdout to fd3'
99
+  steps:
100
+  - send_line: exec 3>&1; echo test >&3
101
+  expect_output: test
102
+  match_type: contains
103
+- name: '56. FILE DESCRIPTOR DUPLICATION: dup stdin from fd'
104
+  steps:
105
+  - send_line: exec 3</dev/null; cat <&3; exec 3<&-; echo ok
106
+  expect_output: ok
107
+  match_type: contains
108
+- name: '57. SET -F (NOGLOB): noglob disables expansion'
109
+  steps:
110
+  - send_line: set -f; echo /tmp/*.xyz; set +f
111
+  expect_output: '/tmp/\*.xyz'
112
+  match_type: regex
113
+  auto_fixed: shell_execution
114
+- name: '57. SET -F (NOGLOB): noglob with literal star'
115
+  steps:
116
+  - send_line: set -f; VAR="a * b"; echo $VAR; set +f
117
+  expect_output: 'a \* b'
118
+  match_type: regex
119
+  auto_fixed: shell_execution
120
+- name: '57. SET -F (NOGLOB): glob after set +f'
121
+  steps:
122
+  - send_line: set -f; set +f; echo /tmp 2>/dev/null | grep -c tmp
123
+  expect_output: '1'
124
+  match_type: contains
125
+- name: '58. SET -X (XTRACE): xtrace shows commands'
126
+  steps:
127
+  - send_line: set -x; echo test 2>&1 | grep -c echo; set +x
128
+  expect_output: '[0-9]+'
129
+  match_type: regex
130
+- name: '58. SET -X (XTRACE): xtrace in function'
131
+  steps:
132
+  - send_line: f() { set -x; echo inner 2>&1; set +x; }; f | grep -c echo
133
+  expect_output: '[0-9]+'
134
+  match_type: regex
135
+- name: '59. SET -V (VERBOSE): verbose shows input'
136
+  steps:
137
+  - send_line: 'set -v; : test 2>&1 | grep -c test; set +v'
138
+  expect_output: '[0-9]+'
139
+  match_type: regex
140
+- name: '60. SET -A (ALLEXPORT): allexport exports vars'
141
+  steps:
142
+  - send_line: set -a; TEST_VAR=value; sh -c "echo $TEST_VAR"
143
+  expect_output: value
144
+  match_type: contains
145
+  auto_fixed: shell_execution
146
+- name: '60. SET -A (ALLEXPORT): allexport off'
147
+  steps:
148
+  - send_line: set +a; TEST2=val; sh -c "echo ${TEST2:-empty}"
149
+  expect_output: empty
150
+  match_type: contains
151
+  auto_fixed: shell_execution
152
+- name: '61. TRAP WITH SIGNALS: trap INT signal'
153
+  steps:
154
+  - send_line: trap "echo caught" INT; trap | grep INT
155
+  expect_output: ''
156
+  match_type: exact
157
+- name: '61. TRAP WITH SIGNALS: trap TERM signal'
158
+  steps:
159
+  - send_line: trap "echo term" TERM; trap | grep TERM
160
+  expect_output: ''
161
+  match_type: exact
162
+- name: '61. TRAP WITH SIGNALS: trap HUP signal'
163
+  steps:
164
+  - send_line: trap "echo hup" HUP; trap | grep HUP
165
+  expect_output: ''
166
+  match_type: exact
167
+- name: '61. TRAP WITH SIGNALS: trap with number'
168
+  steps:
169
+  - send_line: trap "echo sig15" 15; trap | grep -c 15
170
+  expect_output: '[0-9]+'
171
+  match_type: regex
172
+- name: '62. TRAP INHERITANCE IN SUBSHELLS: trap not inherited'
173
+  steps:
174
+  - send_line: trap "echo parent" EXIT; (trap | grep -c EXIT || echo 0)
175
+  expect_output: '[0-9]+'
176
+  match_type: regex
177
+- name: '62. TRAP INHERITANCE IN SUBSHELLS: subshell can set trap'
178
+  steps:
179
+  - send_line: (trap "echo sub" EXIT; exit 0)
180
+  expect_output: sub
181
+  match_type: contains
182
+  auto_fixed: shell_execution
183
+- name: '63. PARAMETER EXPANSION :? ERROR: no error if set'
184
+  steps:
185
+  - send_line: VAR=test; echo ${VAR:?error}
186
+  expect_output: test
187
+  match_type: contains
188
+- name: '64. PARAMETER EXPANSION WITH SPECIAL PARAMS: length of positional params'
189
+  steps:
190
+  - send_line: set -- a b c; echo ${#@}
191
+  expect_output: '3'
192
+  match_type: contains
193
+  auto_fixed: shell_execution
194
+- name: '64. PARAMETER EXPANSION WITH SPECIAL PARAMS: length of $*'
195
+  steps:
196
+  - send_line: set -- x y; echo ${#*}
197
+  expect_output: '2'
198
+  match_type: contains
199
+  auto_fixed: shell_execution
200
+- name: '64. PARAMETER EXPANSION WITH SPECIAL PARAMS: length of $1'
201
+  steps:
202
+  - send_line: set -- hello; echo ${#1}
203
+  expect_output: '5'
204
+  match_type: contains
205
+  auto_fixed: shell_execution
206
+- name: '65. WAIT WITH ARGUMENTS: wait specific PID'
207
+  steps:
208
+  - send_line: sleep 0.1 & pid=$!; wait $pid; echo $?
209
+  expect_output: '0'
210
+  match_type: contains
211
+  auto_fixed: shell_execution
212
+- name: '65. WAIT WITH ARGUMENTS: wait all background'
213
+  steps:
214
+  - send_line: (sleep 0.1 &); wait; echo ok
215
+  expect_output: ok
216
+  match_type: contains
217
+- name: '66. IFS EDGE CASES: empty IFS'
218
+  steps:
219
+  - send_line: IFS=; VAR="a b c"; set -- $VAR; echo $#
220
+  expect_output: '1'
221
+  match_type: contains
222
+  auto_fixed: shell_execution
223
+- name: '66. IFS EDGE CASES: IFS whitespace only'
224
+  steps:
225
+  - send_line: IFS=" \t\n"; VAR="a  b"; set -- $VAR; echo $# $1 $2
226
+  expect_output: 2 a b
227
+  match_type: contains
228
+  auto_fixed: shell_execution
229
+- name: '66. IFS EDGE CASES: IFS custom delimiter'
230
+  steps:
231
+  - send_line: IFS=,; VAR="a,b,c"; set -- $VAR; echo $2
232
+  expect_output: b
233
+  match_type: contains
234
+  auto_fixed: shell_execution
235
+- name: '66. IFS EDGE CASES: IFS leading delimiters'
236
+  steps:
237
+  - send_line: IFS=:; VAR=":a:b"; set -- $VAR; echo $#
238
+  expect_output: '3'
239
+  match_type: contains
240
+  auto_fixed: shell_execution
241
+- name: '67. ARITHMETIC BITWISE OPERATORS: bitwise AND'
242
+  steps:
243
+  - send_line: echo $((12 & 10))
244
+  expect_output: '8'
245
+  match_type: contains
246
+  auto_fixed: shell_execution
247
+- name: '67. ARITHMETIC BITWISE OPERATORS: bitwise OR'
248
+  steps:
249
+  - send_line: echo $((12 | 10))
250
+  expect_output: '14'
251
+  match_type: contains
252
+  auto_fixed: shell_execution
253
+- name: '67. ARITHMETIC BITWISE OPERATORS: bitwise XOR'
254
+  steps:
255
+  - send_line: echo $((12 ^ 10))
256
+  expect_output: '6'
257
+  match_type: contains
258
+  auto_fixed: shell_execution
259
+- name: '67. ARITHMETIC BITWISE OPERATORS: bitwise NOT'
260
+  steps:
261
+  - send_line: echo $((~5))
262
+  expect_output: '-6'
263
+  match_type: contains
264
+  auto_fixed: shell_execution
265
+- name: '67. ARITHMETIC BITWISE OPERATORS: left shift'
266
+  steps:
267
+  - send_line: echo $((3 << 2))
268
+  expect_output: '12'
269
+  match_type: contains
270
+  auto_fixed: shell_execution
271
+- name: '67. ARITHMETIC BITWISE OPERATORS: right shift'
272
+  steps:
273
+  - send_line: echo $((12 >> 2))
274
+  expect_output: '3'
275
+  match_type: contains
276
+  auto_fixed: shell_execution
277
+- name: '68. ARITHMETIC ASSIGNMENT OPERATORS: add assign'
278
+  steps:
279
+  - send_line: X=5; echo $((X += 3)); echo $X
280
+  expect_output: '8'
281
+  match_type: contains
282
+  auto_fixed: shell_execution
283
+- name: '68. ARITHMETIC ASSIGNMENT OPERATORS: subtract assign'
284
+  steps:
285
+  - send_line: X=10; echo $((X -= 3)); echo $X
286
+  expect_output: '7'
287
+  match_type: contains
288
+  auto_fixed: shell_execution
289
+- name: '68. ARITHMETIC ASSIGNMENT OPERATORS: multiply assign'
290
+  steps:
291
+  - send_line: X=4; echo $((X *= 2)); echo $X
292
+  expect_output: '8'
293
+  match_type: contains
294
+  auto_fixed: shell_execution
295
+- name: '68. ARITHMETIC ASSIGNMENT OPERATORS: divide assign'
296
+  steps:
297
+  - send_line: X=20; echo $((X /= 4)); echo $X
298
+  expect_output: '5'
299
+  match_type: contains
300
+  auto_fixed: shell_execution
301
+- name: '68. ARITHMETIC ASSIGNMENT OPERATORS: modulo assign'
302
+  steps:
303
+  - send_line: X=17; echo $((X %= 5)); echo $X
304
+  expect_output: '2'
305
+  match_type: contains
306
+  auto_fixed: shell_execution
307
+- name: '69. ARITHMETIC INCREMENT/DECREMENT: post increment'
308
+  steps:
309
+  - send_line: X=5; echo $((X++)); echo $X
310
+  expect_output: '5'
311
+  match_type: contains
312
+  auto_fixed: shell_execution
313
+- name: '69. ARITHMETIC INCREMENT/DECREMENT: pre increment'
314
+  steps:
315
+  - send_line: X=5; echo $((++X)); echo $X
316
+  expect_output: '6'
317
+  match_type: contains
318
+  auto_fixed: shell_execution
319
+- name: '69. ARITHMETIC INCREMENT/DECREMENT: post decrement'
320
+  steps:
321
+  - send_line: X=5; echo $((X--)); echo $X
322
+  expect_output: '5'
323
+  match_type: contains
324
+  auto_fixed: shell_execution
325
+- name: '69. ARITHMETIC INCREMENT/DECREMENT: pre decrement'
326
+  steps:
327
+  - send_line: X=5; echo $((--X)); echo $X
328
+  expect_output: '4'
329
+  match_type: contains
330
+  auto_fixed: shell_execution
331
+- name: '70. ARITHMETIC TERNARY OPERATOR: ternary true'
332
+  steps:
333
+  - send_line: 'echo $((5 > 3 ? 10 : 20))'
334
+  expect_output: '10'
335
+  match_type: contains
336
+  auto_fixed: shell_execution
337
+- name: '70. ARITHMETIC TERNARY OPERATOR: ternary false'
338
+  steps:
339
+  - send_line: 'echo $((5 < 3 ? 10 : 20))'
340
+  expect_output: '20'
341
+  match_type: contains
342
+  auto_fixed: shell_execution
343
+- name: '70. ARITHMETIC TERNARY OPERATOR: ternary nested'
344
+  steps:
345
+  - send_line: 'echo $((1 ? 2 : 3 ? 4 : 5))'
346
+  expect_output: '2'
347
+  match_type: contains
348
+  auto_fixed: shell_execution
349
+- name: '71. PIPELINE NEGATION: negate pipeline'
350
+  steps:
351
+  - send_line: '! echo test | grep -q xyz; echo $?'
352
+  expect_output: '0'
353
+  match_type: contains
354
+  auto_fixed: shell_execution
355
+- name: '72. THREE-STAGE PIPELINES: three stage pipe'
356
+  steps:
357
+  - send_line: echo abc | tr a A | tr b B
358
+  expect_output: ABc
359
+  match_type: contains
360
+- name: '72. THREE-STAGE PIPELINES: four stage pipe'
361
+  steps:
362
+  - send_line: echo test | cat | cat | wc -l
363
+  expect_output: '1'
364
+  match_type: contains
365
+- name: '73. CDPATH VARIABLE: CDPATH usage'
366
+  steps:
367
+  - send_line: mkdir -p /tmp/posix_cdpath_test/subdir; CDPATH=/tmp/posix_cdpath_test; (cd subdir 2>/dev/null && pwd) | grep -c subdir; rm -rf /tmp/posix_cdpath_test
368
+  expect_output: '[0-9]+'
369
+  match_type: regex
370
+- name: '74. OLDPWD VARIABLE: OLDPWD set'
371
+  steps:
372
+  - send_line: OLD=/tmp; cd /tmp >/dev/null; cd / >/dev/null; echo $OLDPWD | grep
373
+      -c tmp
374
+  expect_output: '1'
375
+  match_type: contains
376
+  auto_fixed: shell_execution
377
+- name: '74. OLDPWD VARIABLE: cd - uses OLDPWD'
378
+  steps:
379
+  - send_line: cd /tmp >/dev/null; cd / >/dev/null; cd - >/dev/null; pwd | grep -c tmp
380
+  expect_output: '[0-9]+'
381
+  match_type: regex
382
+- name: '75. PATHNAME EXPANSION - BRACKET EXPRESSIONS: bracket range'
383
+  steps:
384
+  - send_line: ls /tmp/posix_advanced_test_bracket/[a-b]1.txt 2>/dev/null | wc -l
385
+  expect_output: '[0-9]+'
386
+  match_type: regex
387
+- name: '75. PATHNAME EXPANSION - BRACKET EXPRESSIONS: bracket negation'
388
+  steps:
389
+  - send_line: ls /tmp/posix_advanced_test_bracket/[!a]*.txt 2>/dev/null | wc -l
390
+  expect_output: '[0-9]+'
391
+  match_type: regex
392
+- name: '75. PATHNAME EXPANSION - BRACKET EXPRESSIONS: bracket char class'
393
+  steps:
394
+  - send_line: ls /tmp/posix_advanced_test_bracket/[[:lower:]]1.txt 2>/dev/null | wc -l
395
+  expect_output: '[0-9]+'
396
+  match_type: regex
397
+- name: '76. PATHNAME EXPANSION - DOTFILE MATCHING: star no dotfiles'
398
+  steps:
399
+  - send_line: ls /tmp/posix_advanced_test_dotfile/* 2>/dev/null | wc -l
400
+  expect_output: '[0-9]+'
401
+  match_type: regex
402
+- name: '76. PATHNAME EXPANSION - DOTFILE MATCHING: explicit dot match'
403
+  steps:
404
+  - send_line: ls /tmp/posix_advanced_test_dotfile/.* 2>/dev/null | grep -c hidden
405
+  expect_output: '[0-9]+'
406
+  match_type: regex
407
+- name: '77. FOR LOOP VARIATIONS: for with glob'
408
+  steps:
409
+  - send_line: touch /tmp/posix_for_1.txt /tmp/posix_for_2.txt /tmp/posix_for_3.txt; for f in /tmp/posix_for_*.txt; do echo $f; done | wc -l; rm /tmp/posix_for_*.txt
410
+  expect_output: '[0-9]+'
411
+  match_type: regex
412
+- name: '77. FOR LOOP VARIATIONS: for with no items'
413
+  steps:
414
+  - send_line: for x in; do echo $x; done; echo empty
415
+  expect_output: empty
416
+  match_type: contains
417
+- name: '77. FOR LOOP VARIATIONS: for with quoted items'
418
+  steps:
419
+  - send_line: for i in "a b" "c d"; do echo $i; done | wc -l
420
+  expect_output: '[0-9]+'
421
+  match_type: regex
422
+- name: '78. CASE PATTERN MATCHING: case multiple pattern'
423
+  steps:
424
+  - send_line: x=b; case $x in a|b|c) echo match;; *) echo no;; esac
425
+  expect_output: match
426
+  match_type: contains
427
+  auto_fixed: shell_execution
428
+- name: '78. CASE PATTERN MATCHING: case glob pattern'
429
+  steps:
430
+  - send_line: x=hello; case $x in h*) echo prefix;; esac
431
+  expect_output: prefix
432
+  match_type: contains
433
+  auto_fixed: shell_execution
434
+- name: '78. CASE PATTERN MATCHING: case question mark'
435
+  steps:
436
+  - send_line: x=ab; case $x in ??) echo two;; esac
437
+  expect_output: two
438
+  match_type: contains
439
+  auto_fixed: shell_execution
440
+- name: '78. CASE PATTERN MATCHING: case bracket'
441
+  steps:
442
+  - send_line: x=a; case $x in [abc]) echo bracket;; esac
443
+  expect_output: bracket
444
+  match_type: contains
445
+  auto_fixed: shell_execution
446
+- name: '79. FUNCTION VARIATIONS: function recursion'
447
+  steps:
448
+  - send_line: fact() { if [ $1 -le 1 ]; then echo 1; else echo $(($1 * $(fact $(($1
449
+      - 1))))); fi; }; fact 5
450
+  expect_output: '120'
451
+  match_type: contains
452
+  auto_fixed: shell_execution
453
+- name: '79. FUNCTION VARIATIONS: function unset'
454
+  steps:
455
+  - send_line: f() { echo test; }; f; unset -f f; command -v f >/dev/null 2>&1; echo $?
456
+  expect_output: test
457
+  match_type: contains
458
+  auto_fixed: shell_execution
459
+- name: '79. FUNCTION VARIATIONS: nested return'
460
+  steps:
461
+  - send_line: a() { b; echo $?; }; b() { return 42; }; a
462
+  expect_output: '42'
463
+  match_type: contains
464
+  auto_fixed: shell_execution
465
+- name: '80. EXPANSION IN DIFFERENT CONTEXTS: tilde in assignment'
466
+  steps:
467
+  - send_line: VAR=~; echo $VAR | grep -c ^/
468
+  expect_output: '1'
469
+  match_type: contains
470
+- name: '80. EXPANSION IN DIFFERENT CONTEXTS: expansion in case'
471
+  steps:
472
+  - send_line: VAR=test; case $VAR in test) echo match;; esac
473
+  expect_output: match
474
+  match_type: contains
475
+  auto_fixed: shell_execution
476
+- name: '80. EXPANSION IN DIFFERENT CONTEXTS: no expansion in quotes'
477
+  steps:
478
+  - send_line: echo "~" | grep -c "~"
479
+  expect_output: '1'
480
+  match_type: contains
481
+- name: '81. REDIRECTION ORDER AND PRECEDENCE: multiple redirects'
482
+  steps:
483
+  - send_line: echo test >/tmp/redir1 2>&1 >/tmp/redir2; cat /tmp/redir1 /tmp/redir2 2>/dev/null | wc -l; rm -f /tmp/redir1 /tmp/redir2
484
+  expect_output: '[0-9]+'
485
+  match_type: regex
486
+- name: '81. REDIRECTION ORDER AND PRECEDENCE: redirect compound cmd'
487
+  steps:
488
+  - send_line: '{ echo a; echo b; } >/tmp/redir_compound; wc -l < /tmp/redir_compound; rm -f /tmp/redir_compound'
489
+  expect_output: '[0-9]+'
490
+  match_type: regex
491
+- name: '83. SPECIAL PARAMETERS - ADDITIONAL: PPID is numeric'
492
+  steps:
493
+  - send_line: echo $PPID | grep -c "^[0-9]*$"
494
+  expect_output: '1'
495
+  match_type: contains
496
+  auto_fixed: shell_execution
497
+- name: '83. SPECIAL PARAMETERS - ADDITIONAL: LINENO exists'
498
+  steps:
499
+  - send_line: echo $LINENO | grep -c "^[0-9]*$"
500
+  expect_output: '1'
501
+  match_type: contains
502
+  auto_fixed: shell_execution
503
+- name: '84. ALIAS AND UNALIAS: alias definition'
504
+  steps:
505
+  - send_line: alias ll="ls -l"; alias ll | grep -c "ls -l"
506
+  expect_output: '[0-9]+'
507
+  match_type: regex
508
+- name: '84. ALIAS AND UNALIAS: unalias removes'
509
+  steps:
510
+  - send_line: alias test_alias=echo; unalias test_alias; alias test_alias 2>&1 | grep -c "not found"
511
+  expect_output: '[0-9]+'
512
+  match_type: regex
513
+- name: '85. HASH BUILTIN OPERATIONS: hash -r clears'
514
+  steps:
515
+  - send_line: hash -r; echo $?
516
+  expect_output: '0'
517
+  match_type: contains
518
+  auto_fixed: shell_execution
519
+- name: '86. MULTIPLE SEMICOLONS AND EDGE CASES: multiple semicolons'
520
+  steps:
521
+  - send_line: echo a;; echo b
522
+  expect_output: a
523
+  match_type: contains
524
+- name: '86. MULTIPLE SEMICOLONS AND EDGE CASES: semicolon at start'
525
+  steps:
526
+  - send_line: ; echo test
527
+  expect_output: test
528
+  match_type: contains
529
+- name: '88. COMMENT HANDLING: comment after command'
530
+  steps:
531
+  - send_line: 'echo visible # this is comment'
532
+  expect_output: visible
533
+  match_type: contains
534
+- name: '89. QUOTING EDGE CASES: empty string quotes'
535
+  steps:
536
+  - send_line: echo "" | wc -l
537
+  expect_output: '1'
538
+  match_type: contains
539
+- name: '89. QUOTING EDGE CASES: adjacent quotes'
540
+  steps:
541
+  - send_line: echo "a"b"c"
542
+  expect_output: abc
543
+  match_type: contains
544
+- name: '89. QUOTING EDGE CASES: quote within quote'
545
+  steps:
546
+  - send_line: echo test
547
+  expect_output: test
548
+  match_type: contains
549
+- name: '90. COMPOUND COMMAND REDIRECTION: subshell with redirect'
550
+  steps:
551
+  - send_line: (echo a; echo b) | wc -l
552
+  expect_output: '2'
553
+  match_type: contains
554
+- name: '90. COMPOUND COMMAND REDIRECTION: brace group redirect'
555
+  steps:
556
+  - send_line: '{ echo x; echo y; } | wc -l'
557
+  expect_output: '2'
558
+  match_type: contains
559
+- name: '90. COMPOUND COMMAND REDIRECTION: if statement redirect'
560
+  steps:
561
+  - send_line: if true; then echo yes; fi | cat
562
+  expect_output: 'yes'
563
+  match_type: contains
564
+  auto_fixed: shell_execution
suites/interactive/posix/posix_basic_auto.yamladded
@@ -0,0 +1,553 @@
1
+metadata:
2
+  category: Test
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '1. POSIX BASIC COMMANDS: echo simple'
8
+  steps:
9
+  - send_line: echo hello
10
+  expect_output: hello
11
+  match_type: contains
12
+- name: '1. POSIX BASIC COMMANDS: echo with args'
13
+  steps:
14
+  - send_line: echo one two three
15
+  expect_output: one two three
16
+  match_type: contains
17
+- name: '1. POSIX BASIC COMMANDS: printf basic'
18
+  steps:
19
+  - send_line: printf 'test\n'
20
+  expect_output: test
21
+  match_type: contains
22
+  auto_fixed: shell_execution
23
+- name: '1. POSIX BASIC COMMANDS: printf with args'
24
+  steps:
25
+  - send_line: printf '%s %d\n' hello 42
26
+  expect_output: hello 42
27
+  match_type: contains
28
+  auto_fixed: shell_execution
29
+- name: '2. POSIX VARIABLE EXPANSION: simple variable'
30
+  steps:
31
+  - send_line: VAR=test; echo $VAR
32
+  expect_output: test
33
+  match_type: contains
34
+- name: '2. POSIX VARIABLE EXPANSION: variable in quotes'
35
+  steps:
36
+  - send_line: VAR=test; echo "$VAR"
37
+  expect_output: test
38
+  match_type: contains
39
+- name: '2. POSIX VARIABLE EXPANSION: multiple vars'
40
+  steps:
41
+  - send_line: A=hello; B=world; echo $A $B
42
+  expect_output: hello world
43
+  match_type: contains
44
+- name: '2. POSIX VARIABLE EXPANSION: undefined variable'
45
+  steps:
46
+  - send_line: echo $UNDEFINED_VAR_XYZ_987
47
+  expect_output: ''
48
+  match_type: exact
49
+- name: '3. POSIX PARAMETER EXPANSION: default value'
50
+  steps:
51
+  - send_line: echo "${UNSET:-default}"
52
+  expect_output: default
53
+  match_type: contains
54
+- name: '3. POSIX PARAMETER EXPANSION: assign default'
55
+  steps:
56
+  - send_line: UNSET=; echo "${UNSET:=assigned}"; echo $UNSET
57
+  expect_output: assigned
58
+  match_type: contains
59
+- name: '3. POSIX PARAMETER EXPANSION: error if unset'
60
+  steps:
61
+  - send_line: echo "${VAR:+alternative}"
62
+  expect_output: ''
63
+  match_type: exact
64
+- name: '3. POSIX PARAMETER EXPANSION: string length'
65
+  steps:
66
+  - send_line: VAR=hello; echo "${#VAR}"
67
+  expect_output: '5'
68
+  match_type: contains
69
+- name: '3. POSIX PARAMETER EXPANSION: remove shortest prefix'
70
+  steps:
71
+  - send_line: VAR=foo.bar.baz; echo "${VAR#*.}"
72
+  expect_output: bar.baz
73
+  match_type: contains
74
+- name: '3. POSIX PARAMETER EXPANSION: remove longest prefix'
75
+  steps:
76
+  - send_line: VAR=foo.bar.baz; echo "${VAR##*.}"
77
+  expect_output: baz
78
+  match_type: contains
79
+  auto_fixed: shell_execution
80
+- name: '3. POSIX PARAMETER EXPANSION: prefix no match'
81
+  steps:
82
+  - send_line: VAR=hello; echo "${VAR#x*}"
83
+  expect_output: hello
84
+  match_type: contains
85
+  auto_fixed: shell_execution
86
+- name: '3. POSIX PARAMETER EXPANSION: prefix remove slash'
87
+  steps:
88
+  - send_line: VAR=/usr/local/bin; echo "${VAR#/*/}"
89
+  expect_output: local/bin
90
+  match_type: contains
91
+  auto_fixed: shell_execution
92
+- name: '3. POSIX PARAMETER EXPANSION: remove shortest suffix'
93
+  steps:
94
+  - send_line: VAR=foo.bar.baz; echo "${VAR%.*}"
95
+  expect_output: foo.bar
96
+  match_type: contains
97
+  auto_fixed: shell_execution
98
+- name: '3. POSIX PARAMETER EXPANSION: remove longest suffix'
99
+  steps:
100
+  - send_line: VAR=foo.bar.baz; echo "${VAR%%.*}"
101
+  expect_output: foo
102
+  match_type: contains
103
+  auto_fixed: shell_execution
104
+- name: '3. POSIX PARAMETER EXPANSION: suffix no match'
105
+  steps:
106
+  - send_line: VAR=hello; echo "${VAR%x*}"
107
+  expect_output: hello
108
+  match_type: contains
109
+  auto_fixed: shell_execution
110
+- name: '3. POSIX PARAMETER EXPANSION: suffix remove extension'
111
+  steps:
112
+  - send_line: VAR=file.tar.gz; echo "${VAR%.gz}"
113
+  expect_output: file.tar
114
+  match_type: contains
115
+  auto_fixed: shell_execution
116
+- name: '4. POSIX COMMAND SUBSTITUTION: backtick substitution'
117
+  steps:
118
+  - send_line: echo `echo test`
119
+  expect_output: test
120
+  match_type: contains
121
+- name: '4. POSIX COMMAND SUBSTITUTION: dollar paren substitution'
122
+  steps:
123
+  - send_line: echo $(echo test)
124
+  expect_output: test
125
+  match_type: contains
126
+- name: '4. POSIX COMMAND SUBSTITUTION: nested substitution'
127
+  steps:
128
+  - send_line: echo $(echo $(echo nested))
129
+  expect_output: nested
130
+  match_type: contains
131
+  auto_fixed: shell_execution
132
+- name: '5. POSIX ARITHMETIC: expr addition'
133
+  steps:
134
+  - send_line: expr 5 + 3
135
+  expect_output: '8'
136
+  match_type: contains
137
+  auto_fixed: shell_execution
138
+- name: '5. POSIX ARITHMETIC: expr multiplication'
139
+  steps:
140
+  - send_line: expr 4 \* 3
141
+  expect_output: '12'
142
+  match_type: contains
143
+  auto_fixed: shell_execution
144
+- name: '5. POSIX ARITHMETIC: expr division'
145
+  steps:
146
+  - send_line: expr 15 / 3
147
+  expect_output: '5'
148
+  match_type: contains
149
+  auto_fixed: shell_execution
150
+- name: '6. POSIX REDIRECTION: output redirect'
151
+  steps:
152
+  - send_line: echo test > /tmp/posix_test_out; cat /tmp/posix_test_out
153
+  expect_output: test
154
+  match_type: contains
155
+- name: '6. POSIX REDIRECTION: append redirect'
156
+  steps:
157
+  - send_line: echo line1 > /tmp/posix_test_app; echo line2 >> /tmp/posix_test_app; wc -l < /tmp/posix_test_app
158
+  expect_output: '2'
159
+  match_type: contains
160
+- name: '6. POSIX REDIRECTION: input redirect'
161
+  steps:
162
+  - send_line: echo input > /tmp/posix_test_in; cat < /tmp/posix_test_in
163
+  expect_output: input
164
+  match_type: contains
165
+- name: '6. POSIX REDIRECTION: stderr redirect'
166
+  steps:
167
+  - send_line: ls /nonexistent 2>&1 | grep -c 'cannot access\|No such\|not found'
168
+  expect_output: '1'
169
+  match_type: contains
170
+- name: '7. POSIX PIPELINES: simple pipe'
171
+  steps:
172
+  - send_line: echo hello | cat
173
+  expect_output: hello
174
+  match_type: contains
175
+- name: '7. POSIX PIPELINES: two-stage pipe'
176
+  steps:
177
+  - send_line: echo test | cat | tr t T
178
+  expect_output: TesT
179
+  match_type: contains
180
+- name: '7. POSIX PIPELINES: pipe with filter'
181
+  steps:
182
+  - send_line: printf 'a\nb\nc\n' | grep b
183
+  expect_output: b
184
+  match_type: contains
185
+  auto_fixed: shell_execution
186
+- name: '8. POSIX TEST COMMAND: test -f file (exit code)'
187
+  steps:
188
+  - send_line: touch /tmp/posix_test_file && test -f /tmp/posix_test_file
189
+  - send_line: echo "EXIT=$?"
190
+  expect_output: EXIT=0
191
+  match_type: contains
192
+- name: '8. POSIX TEST COMMAND: test -d directory (exit code)'
193
+  steps:
194
+  - send_line: test -d /tmp
195
+  - send_line: echo "EXIT=$?"
196
+  expect_output: EXIT=0
197
+  match_type: contains
198
+- name: '8. POSIX TEST COMMAND: test -n nonempty (exit code)'
199
+  steps:
200
+  - send_line: test -n 'hello'
201
+  - send_line: echo "EXIT=$?"
202
+  expect_output: EXIT=0
203
+  match_type: contains
204
+- name: '8. POSIX TEST COMMAND: test -z empty (exit code)'
205
+  steps:
206
+  - send_line: test -z ''
207
+  - send_line: echo "EXIT=$?"
208
+  expect_output: EXIT=0
209
+  match_type: contains
210
+- name: '8. POSIX TEST COMMAND: test string = (exit code)'
211
+  steps:
212
+  - send_line: test 'hello' = 'hello'
213
+  - send_line: echo "EXIT=$?"
214
+  expect_output: EXIT=0
215
+  match_type: contains
216
+- name: '8. POSIX TEST COMMAND: test string != (exit code)'
217
+  steps:
218
+  - send_line: test 'hello' != 'world'
219
+  - send_line: echo "EXIT=$?"
220
+  expect_output: EXIT=0
221
+  match_type: contains
222
+- name: '8. POSIX TEST COMMAND: test number -eq (exit code)'
223
+  steps:
224
+  - send_line: test 5 -eq 5
225
+  - send_line: echo "EXIT=$?"
226
+  expect_output: EXIT=0
227
+  match_type: contains
228
+- name: '8. POSIX TEST COMMAND: test number -ne (exit code)'
229
+  steps:
230
+  - send_line: test 5 -ne 3
231
+  - send_line: echo "EXIT=$?"
232
+  expect_output: EXIT=0
233
+  match_type: contains
234
+- name: '8. POSIX TEST COMMAND: test number -gt (exit code)'
235
+  steps:
236
+  - send_line: test 5 -gt 3
237
+  - send_line: echo "EXIT=$?"
238
+  expect_output: EXIT=0
239
+  match_type: contains
240
+- name: '8. POSIX TEST COMMAND: test number -ge (exit code)'
241
+  steps:
242
+  - send_line: test 5 -ge 5
243
+  - send_line: echo "EXIT=$?"
244
+  expect_output: EXIT=0
245
+  match_type: contains
246
+- name: '8. POSIX TEST COMMAND: test number -lt (exit code)'
247
+  steps:
248
+  - send_line: test 3 -lt 5
249
+  - send_line: echo "EXIT=$?"
250
+  expect_output: EXIT=0
251
+  match_type: contains
252
+- name: '8. POSIX TEST COMMAND: test number -le (exit code)'
253
+  steps:
254
+  - send_line: test 3 -le 3
255
+  - send_line: echo "EXIT=$?"
256
+  expect_output: EXIT=0
257
+  match_type: contains
258
+- name: '9. POSIX CONDITIONALS: if true'
259
+  steps:
260
+  - send_line: if true; then echo yes; fi
261
+  expect_output: 'yes'
262
+  match_type: contains
263
+  auto_fixed: shell_execution
264
+- name: '9. POSIX CONDITIONALS: if false else'
265
+  steps:
266
+  - send_line: if false; then echo no; else echo yes; fi
267
+  expect_output: 'yes'
268
+  match_type: contains
269
+  auto_fixed: shell_execution
270
+- name: '9. POSIX CONDITIONALS: if-elif-else'
271
+  steps:
272
+  - send_line: X=2; if [ $X -eq 1 ]; then echo one; elif [ $X -eq 2 ]; then echo two; else echo other; fi
273
+  expect_output: two
274
+  match_type: contains
275
+- name: '10. POSIX LOOPS: for loop'
276
+  steps:
277
+  - send_line: for i in a b c; do echo $i; done
278
+  expect_output: a
279
+  match_type: contains
280
+  auto_fixed: shell_execution
281
+- name: '10. POSIX LOOPS: while loop'
282
+  steps:
283
+  - send_line: i=3; while [ $i -gt 0 ]; do echo $i; i=$((i - 1)); done
284
+  expect_output: '3'
285
+  match_type: contains
286
+  auto_fixed: shell_execution
287
+- name: '10. POSIX LOOPS: until loop'
288
+  steps:
289
+  - send_line: i=1; until [ $i -gt 3 ]; do echo $i; i=$((i + 1)); done
290
+  expect_output: '1'
291
+  match_type: contains
292
+  auto_fixed: shell_execution
293
+- name: '11. POSIX CASE STATEMENT: case exact match'
294
+  steps:
295
+  - send_line: x=2; case $x in 1) echo one;; 2) echo two;; esac
296
+  expect_output: two
297
+  match_type: contains
298
+  auto_fixed: shell_execution
299
+- name: '11. POSIX CASE STATEMENT: case pattern match'
300
+  steps:
301
+  - send_line: x=hello; case $x in h*) echo h_prefix;; esac
302
+  expect_output: h_prefix
303
+  match_type: contains
304
+  auto_fixed: shell_execution
305
+- name: '11. POSIX CASE STATEMENT: case default'
306
+  steps:
307
+  - send_line: x=z; case $x in a) echo a;; b) echo b;; *) echo default;; esac
308
+  expect_output: default
309
+  match_type: contains
310
+  auto_fixed: shell_execution
311
+- name: '11. POSIX CASE STATEMENT: case multiple patterns'
312
+  steps:
313
+  - send_line: x=b; case $x in a|b|c) echo abc;; *) echo other;; esac
314
+  expect_output: abc
315
+  match_type: contains
316
+  auto_fixed: shell_execution
317
+- name: '12. POSIX FUNCTIONS: simple function'
318
+  steps:
319
+  - send_line: func() { echo hello; }; func
320
+  expect_output: hello
321
+  match_type: contains
322
+  auto_fixed: shell_execution
323
+- name: '12. POSIX FUNCTIONS: function with args'
324
+  steps:
325
+  - send_line: func() { echo $1 $2; }; func foo bar
326
+  expect_output: foo bar
327
+  match_type: contains
328
+  auto_fixed: shell_execution
329
+- name: '12. POSIX FUNCTIONS: function return'
330
+  steps:
331
+  - send_line: func() { return 42; }; func; echo $?
332
+  expect_output: '42'
333
+  match_type: contains
334
+  auto_fixed: shell_execution
335
+- name: '12. POSIX FUNCTIONS: function \$# args'
336
+  steps:
337
+  - send_line: func() { echo $#; }; func a b c
338
+  expect_output: '3'
339
+  match_type: contains
340
+  auto_fixed: shell_execution
341
+- name: '13. POSIX SPECIAL VARIABLES: \$? exit status'
342
+  steps:
343
+  - send_line: true; echo $?
344
+  expect_output: '0'
345
+  match_type: contains
346
+  auto_fixed: shell_execution
347
+- name: '13. POSIX SPECIAL VARIABLES: \$? after false'
348
+  steps:
349
+  - send_line: false; echo $?
350
+  expect_output: '1'
351
+  match_type: contains
352
+  auto_fixed: shell_execution
353
+- name: '13. POSIX SPECIAL VARIABLES: \$# argument count'
354
+  steps:
355
+  - send_line: set -- a b c; echo $#
356
+  expect_output: '3'
357
+  match_type: contains
358
+  auto_fixed: shell_execution
359
+- name: '13. POSIX SPECIAL VARIABLES: \$@ all arguments'
360
+  steps:
361
+  - send_line: set -- a b c; echo $@
362
+  expect_output: a b c
363
+  match_type: contains
364
+  auto_fixed: shell_execution
365
+- name: '13. POSIX SPECIAL VARIABLES: \$* all arguments'
366
+  steps:
367
+  - send_line: set -- a b c; echo $*
368
+  expect_output: a b c
369
+  match_type: contains
370
+  auto_fixed: shell_execution
371
+- name: '13. POSIX SPECIAL VARIABLES: \$0 script name'
372
+  steps:
373
+  - send_line: echo $0 | grep -c sh
374
+  expect_output: '1'
375
+  match_type: contains
376
+  auto_fixed: shell_execution
377
+- name: '14. POSIX LOGICAL OPERATORS: true && true (exit code)'
378
+  steps:
379
+  - send_line: true && true
380
+  - send_line: echo "EXIT=$?"
381
+  expect_output: EXIT=0
382
+  match_type: contains
383
+- name: '14. POSIX LOGICAL OPERATORS: true && false (exit code)'
384
+  steps:
385
+  - send_line: true && false
386
+  - send_line: echo "EXIT=$?"
387
+  expect_output: EXIT=1
388
+  match_type: contains
389
+- name: '14. POSIX LOGICAL OPERATORS: false || true (exit code)'
390
+  steps:
391
+  - send_line: false || true
392
+  - send_line: echo "EXIT=$?"
393
+  expect_output: EXIT=0
394
+  match_type: contains
395
+- name: '14. POSIX LOGICAL OPERATORS: false || false (exit code)'
396
+  steps:
397
+  - send_line: false || false
398
+  - send_line: echo "EXIT=$?"
399
+  expect_output: EXIT=1
400
+  match_type: contains
401
+- name: '14. POSIX LOGICAL OPERATORS: command && echo'
402
+  steps:
403
+  - send_line: true && echo success
404
+  expect_output: success
405
+  match_type: contains
406
+  auto_fixed: shell_execution
407
+- name: '14. POSIX LOGICAL OPERATORS: command || echo'
408
+  steps:
409
+  - send_line: false || echo fallback
410
+  expect_output: fallback
411
+  match_type: contains
412
+  auto_fixed: shell_execution
413
+- name: '14. POSIX LOGICAL OPERATORS: ! negation'
414
+  steps:
415
+  - send_line: '! false && echo negated'
416
+  expect_output: negated
417
+  match_type: contains
418
+  auto_fixed: shell_execution
419
+- name: '15. POSIX QUOTING: single quote literal'
420
+  steps:
421
+  - send_line: echo '$VAR'
422
+  expect_output: \$VAR
423
+  match_type: contains
424
+  auto_fixed: shell_execution
425
+- name: '15. POSIX QUOTING: double quote expand'
426
+  steps:
427
+  - send_line: VAR=test; echo "$VAR"
428
+  expect_output: test
429
+  match_type: contains
430
+- name: '15. POSIX QUOTING: escape in double'
431
+  steps:
432
+  - send_line: echo "test$var"
433
+  expect_output: test
434
+  match_type: contains
435
+  auto_fixed: shell_execution
436
+- name: '15. POSIX QUOTING: backslash escape'
437
+  steps:
438
+  - send_line: echo test\ word
439
+  expect_output: test word
440
+  match_type: contains
441
+- name: '16. POSIX SUBSHELLS: subshell grouping'
442
+  steps:
443
+  - send_line: (echo a; echo b) | wc -l
444
+  expect_output: '2'
445
+  match_type: contains
446
+- name: '16. POSIX SUBSHELLS: subshell var isolation'
447
+  steps:
448
+  - send_line: (VAR=inner; echo $VAR); echo $VAR
449
+  expect_output: inner
450
+  match_type: contains
451
+  auto_fixed: shell_execution
452
+- name: '17. POSIX COMPOUND COMMANDS: command grouping {}'
453
+  steps:
454
+  - send_line: '{ echo a; echo b; } | wc -l'
455
+  expect_output: '2'
456
+  match_type: contains
457
+- name: '17. POSIX COMPOUND COMMANDS: command list ;'
458
+  steps:
459
+  - send_line: echo a; echo b
460
+  expect_output: a
461
+  match_type: contains
462
+- name: '19. POSIX WORD EXPANSION ORDER: expansion order'
463
+  steps:
464
+  - send_line: VAR='a b'; echo $VAR
465
+  expect_output: a b
466
+  match_type: contains
467
+  auto_fixed: shell_execution
468
+- name: '19. POSIX WORD EXPANSION ORDER: quoted expansion'
469
+  steps:
470
+  - send_line: VAR="a b"; echo "$VAR"
471
+  expect_output: a b
472
+  match_type: contains
473
+- name: '20. POSIX PATHNAME EXPANSION (GLOBBING): glob * pattern'
474
+  steps:
475
+  - send_line: ls /tmp/posix_test_glob/*.txt 2>/dev/null | wc -l
476
+  expect_output: '[0-9]+'
477
+  match_type: regex
478
+- name: '20. POSIX PATHNAME EXPANSION (GLOBBING): glob ? pattern'
479
+  steps:
480
+  - send_line: ls /tmp/posix_test_glob/?.txt 2>/dev/null | wc -l
481
+  expect_output: '[0-9]+'
482
+  match_type: regex
483
+- name: '20. POSIX PATHNAME EXPANSION (GLOBBING): glob [abc] pattern'
484
+  steps:
485
+  - send_line: ls /tmp/posix_test_glob/[ab].txt 2>/dev/null | wc -l
486
+  expect_output: '[0-9]+'
487
+  match_type: regex
488
+- name: '21. POSIX FIELD SPLITTING (IFS): default IFS'
489
+  steps:
490
+  - send_line: VAR='a b c'; set -- $VAR; echo $#
491
+  expect_output: '3'
492
+  match_type: contains
493
+  auto_fixed: shell_execution
494
+- name: '21. POSIX FIELD SPLITTING (IFS): custom IFS'
495
+  steps:
496
+  - send_line: IFS=:; VAR='a:b:c'; set -- $VAR; echo $1
497
+  expect_output: a
498
+  match_type: contains
499
+  auto_fixed: shell_execution
500
+- name: '22. POSIX EXIT STATUS: true exit status (exit code)'
501
+  steps:
502
+  - send_line: 'true'
503
+  - send_line: echo "EXIT=$?"
504
+  expect_output: EXIT=0
505
+  match_type: contains
506
+- name: '22. POSIX EXIT STATUS: false exit status (exit code)'
507
+  steps:
508
+  - send_line: 'false'
509
+  - send_line: echo "EXIT=$?"
510
+  expect_output: EXIT=1
511
+  match_type: contains
512
+- name: '22. POSIX EXIT STATUS: command not found (exit code)'
513
+  steps:
514
+  - send_line: nonexistent_command_xyz 2>/dev/null
515
+  - send_line: echo "EXIT=$?"
516
+  expect_output: EXIT=127
517
+  match_type: contains
518
+- name: '22. POSIX EXIT STATUS: return from function (exit code)'
519
+  steps:
520
+  - send_line: func() { return 3; }; func
521
+  - send_line: echo "EXIT=$?"
522
+  expect_output: EXIT=3
523
+  match_type: contains
524
+- name: '23. POSIX SET BUILTIN: set positional'
525
+  steps:
526
+  - send_line: set -- a b c; echo $1 $2 $3
527
+  expect_output: a
528
+  match_type: contains
529
+  auto_fixed: shell_execution
530
+- name: '23. POSIX SET BUILTIN: set shift'
531
+  steps:
532
+  - send_line: set -- a b c; shift; echo $1
533
+  expect_output: b
534
+  match_type: contains
535
+  auto_fixed: shell_execution
536
+- name: '23. POSIX SET BUILTIN: set shift n'
537
+  steps:
538
+  - send_line: set -- a b c d; shift 2; echo $1
539
+  expect_output: c
540
+  match_type: contains
541
+  auto_fixed: shell_execution
542
+- name: '24. POSIX EXPORT: export variable'
543
+  steps:
544
+  - send_line: export VAR=test; sh -c 'echo $VAR'
545
+  expect_output: test
546
+  match_type: contains
547
+  auto_fixed: shell_execution
548
+- name: '25. POSIX READONLY: readonly assignment (exit code)'
549
+  steps:
550
+  - send_line: readonly VAR=test; VAR=new 2>/dev/null
551
+  - send_line: echo "EXIT=$?"
552
+  expect_output: EXIT=1
553
+  match_type: contains
suites/interactive/posix/posix_basic_sample.yamladded
@@ -0,0 +1,93 @@
1
+metadata:
2
+  category: "POSIX Basic Sample"
3
+  description: Sample of converted basic POSIX tests
4
+tests:
5
+- name: echo simple
6
+  steps:
7
+  - send_line: echo hello
8
+  expect_output: hello
9
+  match_type: contains
10
+
11
+- name: echo with args
12
+  steps:
13
+  - send_line: echo one two three
14
+  expect_output: one two three
15
+  match_type: contains
16
+
17
+- name: printf basic
18
+  steps:
19
+  - send_line: printf 'test\n'
20
+  expect_output: test
21
+  match_type: contains
22
+
23
+- name: variable in quotes
24
+  steps:
25
+  - send_line: VAR=test; echo "$VAR"
26
+  expect_output: test
27
+  match_type: contains
28
+
29
+- name: parameter expansion default
30
+  steps:
31
+  - send_line: echo "${UNSET:-default}"
32
+  expect_output: default
33
+  match_type: contains
34
+
35
+- name: string length
36
+  steps:
37
+  - send_line: VAR=hello; echo "${#VAR}"
38
+  expect_output: '5'
39
+  match_type: contains
40
+
41
+- name: remove shortest prefix
42
+  steps:
43
+  - send_line: VAR=foo.bar.baz; echo "${VAR#*.}"
44
+  expect_output: bar.baz
45
+  match_type: contains
46
+
47
+- name: expr addition
48
+  steps:
49
+  - send_line: expr 5 + 3
50
+  expect_output: '8'
51
+  match_type: contains
52
+
53
+- name: if true
54
+  steps:
55
+  - send_line: if true; then echo yes; fi
56
+  expect_output: 'yes'  # Quote to prevent YAML boolean parsing
57
+  match_type: contains
58
+
59
+- name: simple function
60
+  steps:
61
+  - send_line: func() { echo hello; }; func
62
+  expect_output: hello
63
+  match_type: contains
64
+
65
+- name: function with args
66
+  steps:
67
+  - send_line: func() { echo $1 $2; }; func foo bar
68
+  expect_output: foo bar
69
+  match_type: contains
70
+
71
+- name: special var $# count
72
+  steps:
73
+  - send_line: set -- a b c; echo $#
74
+  expect_output: '3'
75
+  match_type: contains
76
+
77
+- name: special var $@ all args
78
+  steps:
79
+  - send_line: set -- a b c; echo $@
80
+  expect_output: a b c
81
+  match_type: contains
82
+
83
+- name: true && echo
84
+  steps:
85
+  - send_line: true && echo success
86
+  expect_output: success
87
+  match_type: contains
88
+
89
+- name: set positional
90
+  steps:
91
+  - send_line: set -- a b c; echo $1 $2 $3
92
+  expect_output: a b c
93
+  match_type: contains
suites/interactive/posix/posix_coverage_auto.yamladded
@@ -0,0 +1,574 @@
1
+metadata:
2
+  category: Coverage
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: octal literal'
8
+  steps:
9
+  - send_line: echo $((010))
10
+  expect_output: '8'
11
+  match_type: contains
12
+  auto_fixed: shell_execution
13
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: hex literal lowercase'
14
+  steps:
15
+  - send_line: echo $((0xff))
16
+  expect_output: '255'
17
+  match_type: contains
18
+  auto_fixed: shell_execution
19
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: hex literal uppercase'
20
+  steps:
21
+  - send_line: echo $((0xFF))
22
+  expect_output: '255'
23
+  match_type: contains
24
+  auto_fixed: shell_execution
25
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: octal in expression'
26
+  steps:
27
+  - send_line: echo $((010 + 1))
28
+  expect_output: '9'
29
+  match_type: contains
30
+  auto_fixed: shell_execution
31
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: hex in expression'
32
+  steps:
33
+  - send_line: echo $((0x10 + 1))
34
+  expect_output: '17'
35
+  match_type: contains
36
+  auto_fixed: shell_execution
37
+- name: '200. ARITHMETIC - OCTAL AND HEX LITERALS: mixed bases'
38
+  steps:
39
+  - send_line: echo $((0x10 + 010 + 10))
40
+  expect_output: '34'
41
+  match_type: contains
42
+  auto_fixed: shell_execution
43
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative literal'
44
+  steps:
45
+  - send_line: echo $((-5))
46
+  expect_output: '-5'
47
+  match_type: contains
48
+  auto_fixed: shell_execution
49
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative in addition'
50
+  steps:
51
+  - send_line: echo $((10 + -3))
52
+  expect_output: '7'
53
+  match_type: contains
54
+  auto_fixed: shell_execution
55
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative in subtraction'
56
+  steps:
57
+  - send_line: echo $((5 - -3))
58
+  expect_output: '8'
59
+  match_type: contains
60
+  auto_fixed: shell_execution
61
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: double negative'
62
+  steps:
63
+  - send_line: echo $((--5))
64
+  expect_output: '5'
65
+  match_type: contains
66
+  auto_fixed: shell_execution
67
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative multiplication'
68
+  steps:
69
+  - send_line: echo $((-3 * -4))
70
+  expect_output: '12'
71
+  match_type: contains
72
+  auto_fixed: shell_execution
73
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative division'
74
+  steps:
75
+  - send_line: echo $((-10 / 3))
76
+  expect_output: '-3'
77
+  match_type: contains
78
+  auto_fixed: shell_execution
79
+- name: '201. ARITHMETIC - NEGATIVE NUMBERS: negative modulo'
80
+  steps:
81
+  - send_line: echo $((-10 % 3))
82
+  expect_output: '-1'
83
+  match_type: contains
84
+  auto_fixed: shell_execution
85
+- name: '202. ARITHMETIC - NESTED EXPRESSIONS: nested arithmetic'
86
+  steps:
87
+  - send_line: echo $((1 + $((2 + 3))))
88
+  expect_output: '6'
89
+  match_type: contains
90
+  auto_fixed: shell_execution
91
+- name: '202. ARITHMETIC - NESTED EXPRESSIONS: deeply nested'
92
+  steps:
93
+  - send_line: echo $((1 + $((2 + $((3 + 4))))))
94
+  expect_output: '10'
95
+  match_type: contains
96
+  auto_fixed: shell_execution
97
+- name: '202. ARITHMETIC - NESTED EXPRESSIONS: nested with vars'
98
+  steps:
99
+  - send_line: a=5; echo $((a + $((a * 2))))
100
+  expect_output: '15'
101
+  match_type: contains
102
+  auto_fixed: shell_execution
103
+- name: '203. ARITHMETIC - COMMA OPERATOR: comma operator'
104
+  steps:
105
+  - send_line: echo $((1, 2, 3))
106
+  expect_output: '3'
107
+  match_type: contains
108
+  auto_fixed: shell_execution
109
+- name: '203. ARITHMETIC - COMMA OPERATOR: comma with assignment'
110
+  steps:
111
+  - send_line: echo $((a=1, b=2, a+b))
112
+  expect_output: '3'
113
+  match_type: contains
114
+  auto_fixed: shell_execution
115
+- name: '203. ARITHMETIC - COMMA OPERATOR: comma side effects'
116
+  steps:
117
+  - send_line: a=0; echo $((a=1, a=a+1, a))
118
+  expect_output: '2'
119
+  match_type: contains
120
+  auto_fixed: shell_execution
121
+- name: '210. WORD SPLITTING - EMPTY IFS: empty IFS no split'
122
+  steps:
123
+  - send_line: IFS=""; var="a b c"; set -- $var; echo $#
124
+  expect_output: '1'
125
+  match_type: contains
126
+  auto_fixed: shell_execution
127
+- name: '210. WORD SPLITTING - EMPTY IFS: empty IFS preserves spaces'
128
+  steps:
129
+  - send_line: IFS=""; var="a  b"; set -- $var; echo "$1"
130
+  expect_output: a  b
131
+  match_type: contains
132
+  auto_fixed: shell_execution
133
+- name: '211. WORD SPLITTING - IFS VARIATIONS: IFS whitespace only'
134
+  steps:
135
+  - send_line: IFS=" "; var="a  b"; set -- $var; echo $#
136
+  expect_output: '2'
137
+  match_type: contains
138
+  auto_fixed: shell_execution
139
+- name: '211. WORD SPLITTING - IFS VARIATIONS: IFS non-whitespace'
140
+  steps:
141
+  - send_line: IFS=":"; var="a:b:c"; set -- $var; echo $#
142
+  expect_output: '3'
143
+  match_type: contains
144
+  auto_fixed: shell_execution
145
+- name: '211. WORD SPLITTING - IFS VARIATIONS: IFS mixed'
146
+  steps:
147
+  - send_line: 'IFS=" :"; var="a : b"; set -- $var; echo $#'
148
+  expect_output: '2'
149
+  match_type: contains
150
+  auto_fixed: shell_execution
151
+- name: '211. WORD SPLITTING - IFS VARIATIONS: IFS tab'
152
+  steps:
153
+  - send_line: "IFS=$(printf '\\t'); var=$(printf 'a\\tb\\tc'); set -- $var; echo $#"
154
+  expect_output: '3'
155
+  match_type: contains
156
+  auto_fixed: shell_execution
157
+- name: '212. WORD SPLITTING - $@ VS $*: $* unquoted'
158
+  steps:
159
+  - send_line: set -- "a b" "c d"; for x in $*; do echo "[$x]"; done
160
+  expect_output: '[a]'
161
+  match_type: contains
162
+  auto_fixed: shell_execution
163
+- name: '212. WORD SPLITTING - $@ VS $*: $@ unquoted'
164
+  steps:
165
+  - send_line: set -- "a b" "c d"; for x in $@; do echo "[$x]"; done
166
+  expect_output: '[a]'
167
+  match_type: contains
168
+  auto_fixed: shell_execution
169
+- name: '212. WORD SPLITTING - $@ VS $*: $* quoted'
170
+  steps:
171
+  - send_line: set -- "a b" "c d"; for x in "$*"; do echo "[$x]"; done
172
+  expect_output: '[a b c d]'
173
+  match_type: contains
174
+  auto_fixed: shell_execution
175
+- name: '212. WORD SPLITTING - $@ VS $*: $@ quoted'
176
+  steps:
177
+  - send_line: set -- "a b" "c d"; for x in "$@"; do echo "[$x]"; done
178
+  expect_output: '[a b]'
179
+  match_type: contains
180
+  auto_fixed: shell_execution
181
+- name: '212. WORD SPLITTING - $@ VS $*: $* with IFS'
182
+  steps:
183
+  - send_line: IFS=:; set -- a b c; echo "$*"
184
+  expect_output: a:b:c
185
+  match_type: contains
186
+  auto_fixed: shell_execution
187
+- name: '212. WORD SPLITTING - $@ VS $*: $@ with IFS'
188
+  steps:
189
+  - send_line: IFS=:; set -- a b c; echo "$@"
190
+  expect_output: a b c
191
+  match_type: contains
192
+  auto_fixed: shell_execution
193
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: :+ empty var'
194
+  steps:
195
+  - send_line: var=""; echo "${var:+set}"
196
+  expect_output: ''
197
+  match_type: exact
198
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: :+ unset var'
199
+  steps:
200
+  - send_line: unset var; echo "${var:+set}"
201
+  expect_output: ''
202
+  match_type: exact
203
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: + empty var'
204
+  steps:
205
+  - send_line: var=""; echo "${var+set}"
206
+  expect_output: set
207
+  match_type: contains
208
+  auto_fixed: shell_execution
209
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: + unset var'
210
+  steps:
211
+  - send_line: unset var; echo "${var+set}"
212
+  expect_output: ''
213
+  match_type: exact
214
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: :- empty var'
215
+  steps:
216
+  - send_line: var=""; echo "${var:-default}"
217
+  expect_output: default
218
+  match_type: contains
219
+  auto_fixed: shell_execution
220
+- name: '220. PARAMETER EXPANSION - EMPTY VS UNSET: - empty var'
221
+  steps:
222
+  - send_line: var=""; echo "${var-default}"
223
+  expect_output: ''
224
+  match_type: exact
225
+- name: '221. PARAMETER EXPANSION - ASSIGNMENT FORMS: := assigns when empty'
226
+  steps:
227
+  - send_line: unset var; echo "${var:=default}"; echo "$var"
228
+  expect_output: default
229
+  match_type: contains
230
+  auto_fixed: shell_execution
231
+- name: '221. PARAMETER EXPANSION - ASSIGNMENT FORMS: = assigns when unset'
232
+  steps:
233
+  - send_line: unset var; echo "${var=default}"; echo "$var"
234
+  expect_output: default
235
+  match_type: contains
236
+  auto_fixed: shell_execution
237
+- name: '221. PARAMETER EXPANSION - ASSIGNMENT FORMS: := with empty'
238
+  steps:
239
+  - send_line: var=""; echo "${var:=default}"; echo "$var"
240
+  expect_output: default
241
+  match_type: contains
242
+  auto_fixed: shell_execution
243
+- name: '221. PARAMETER EXPANSION - ASSIGNMENT FORMS: = with empty'
244
+  steps:
245
+  - send_line: var=""; echo "${var=default}"; echo "$var"
246
+  expect_output: ''
247
+  match_type: exact
248
+- name: '222. PARAMETER EXPANSION - PATTERN IN EXPANSION: nested pattern removal'
249
+  steps:
250
+  - send_line: suffix=.txt; file=test.txt; echo "${file%$suffix}"
251
+  expect_output: test
252
+  match_type: contains
253
+  auto_fixed: shell_execution
254
+- name: '222. PARAMETER EXPANSION - PATTERN IN EXPANSION: var in pattern'
255
+  steps:
256
+  - send_line: pat=t; var=test; echo "${var#$pat}"
257
+  expect_output: est
258
+  match_type: contains
259
+  auto_fixed: shell_execution
260
+- name: '222. PARAMETER EXPANSION - PATTERN IN EXPANSION: var in suffix pattern'
261
+  steps:
262
+  - send_line: pat=st; var=test; echo "${var%$pat}"
263
+  expect_output: te
264
+  match_type: contains
265
+  auto_fixed: shell_execution
266
+- name: '230. TRAP - IGNORE VS RESET: trap ignore'
267
+  steps:
268
+  - send_line: trap "" INT; trap; trap - INT; trap
269
+  expect_output: trap -- '' SIGINT
270
+  match_type: contains
271
+  auto_fixed: shell_execution
272
+- name: '230. TRAP - IGNORE VS RESET: trap reset'
273
+  steps:
274
+  - send_line: trap "echo caught" INT; trap - INT; trap
275
+  expect_output: ''
276
+  match_type: exact
277
+- name: '230. TRAP - IGNORE VS RESET: trap empty string'
278
+  steps:
279
+  - send_line: trap "" EXIT; echo done
280
+  expect_output: done
281
+  match_type: contains
282
+- name: '231. TRAP - IN SUBSHELLS: trap not inherited'
283
+  steps:
284
+  - send_line: trap "echo trap" EXIT; (trap); echo done
285
+  expect_output: done
286
+  match_type: contains
287
+- name: '231. TRAP - IN SUBSHELLS: ignore trap inherited'
288
+  steps:
289
+  - send_line: trap "" INT; (trap)
290
+  expect_output: trap -- '' SIGINT
291
+  match_type: contains
292
+  auto_fixed: shell_execution
293
+- name: '232. TRAP - MULTIPLE SIGNALS: trap multiple'
294
+  steps:
295
+  - send_line: trap "echo exit" EXIT; trap "echo err" ERR 2>/dev/null || true; echo
296
+      done
297
+  expect_output: done
298
+  match_type: contains
299
+- name: '240. SET -e EDGE CASES: set -e with &&'
300
+  steps:
301
+  - send_line: set -e; false && true; echo reached
302
+  expect_output: reached
303
+  match_type: contains
304
+- name: '240. SET -e EDGE CASES: set -e with ||'
305
+  steps:
306
+  - send_line: set -e; false || true; echo reached
307
+  expect_output: reached
308
+  match_type: contains
309
+- name: '240. SET -e EDGE CASES: set -e with !'
310
+  steps:
311
+  - send_line: set -e; ! false; echo reached
312
+  expect_output: reached
313
+  match_type: contains
314
+- name: '240. SET -e EDGE CASES: set -e in if condition'
315
+  steps:
316
+  - send_line: set -e; if false; then echo no; fi; echo reached
317
+  expect_output: reached
318
+  match_type: contains
319
+- name: '240. SET -e EDGE CASES: set -e in while condition'
320
+  steps:
321
+  - send_line: set -e; while false; do echo no; done; echo reached
322
+  expect_output: reached
323
+  match_type: contains
324
+- name: '241. SET -e IN SUBSHELLS: set -e inherited'
325
+  steps:
326
+  - send_line: set -e; (false; echo no) || echo caught
327
+  expect_output: caught
328
+  match_type: contains
329
+- name: '241. SET -e IN SUBSHELLS: set -e in command sub'
330
+  steps:
331
+  - send_line: set -e; x=$(false; echo yes); echo "x=$x"
332
+  expect_output: ''
333
+  match_type: exact
334
+- name: '242. COMMAND NOT FOUND: command not found status'
335
+  steps:
336
+  - send_line: $test_cmd
337
+  expect_output: ''
338
+  match_type: exact
339
+- name: '250. FUNCTION - BUILTIN SHADOWING: function shadows builtin'
340
+  steps:
341
+  - send_line: 'echo() { printf "custom: %s\n" "$1"; }; echo test; unset -f echo'
342
+  expect_output: 'custom: test'
343
+  match_type: contains
344
+  auto_fixed: shell_execution
345
+- name: '250. FUNCTION - BUILTIN SHADOWING: function named cd'
346
+  steps:
347
+  - send_line: cd() { echo "custom cd"; }; cd /tmp; unset -f cd
348
+  expect_output: custom cd
349
+  match_type: contains
350
+  auto_fixed: shell_execution
351
+- name: '251. FUNCTION - REDEFINITION: redefine function'
352
+  steps:
353
+  - send_line: f() { echo v1; }; f; f() { echo v2; }; f
354
+  expect_output: v1
355
+  match_type: contains
356
+  auto_fixed: shell_execution
357
+- name: '252. FUNCTION - INDIRECT RECURSION: mutual recursion'
358
+  steps:
359
+  - send_line: a() { [ $1 -le 0 ] && echo done || b $(($1-1)); }; b() { a $1; }; a
360
+      3
361
+  expect_output: done
362
+  match_type: contains
363
+  auto_fixed: shell_execution
364
+- name: '253. FUNCTION - RETURN EDGE CASES: return outside function'
365
+  steps:
366
+  - send_line: (return 5 2>/dev/null); echo $?
367
+  expect_output: '2'
368
+  match_type: contains
369
+  auto_fixed: shell_execution
370
+- name: '253. FUNCTION - RETURN EDGE CASES: return in sourced file'
371
+  steps:
372
+  - send_line: echo "return 42" > /tmp/ret.sh; . /tmp/ret.sh; echo $?; rm /tmp/ret.sh
373
+  expect_output: '42'
374
+  match_type: contains
375
+  auto_fixed: shell_execution
376
+- name: '260. REDIRECTION - CLOSED FD OPERATIONS: write to closed fd'
377
+  steps:
378
+  - send_line: exec 3>&-; echo test >&3 2>&1 | head -1
379
+  expect_output: Bad file descriptor
380
+  match_type: contains
381
+- name: '260. REDIRECTION - CLOSED FD OPERATIONS: read from closed fd'
382
+  steps:
383
+  - send_line: exec 3<&-; cat <&3 2>&1 | head -1
384
+  expect_output: ''
385
+  match_type: exact
386
+- name: '262. REDIRECTION - NOCLOBBER WITH APPEND: noclobber allows append'
387
+  steps:
388
+  - send_line: set -C; echo a > /tmp/nc_test; echo b >> /tmp/nc_test; cat /tmp/nc_test; rm /tmp/nc_test
389
+  expect_output: a
390
+  match_type: contains
391
+  auto_fixed: shell_execution
392
+- name: '270. PIPELINE - BUILTIN ONLY: pipeline all builtins'
393
+  steps:
394
+  - send_line: 'echo test | { read x; echo "got: $x"; }'
395
+  expect_output: 'got: test'
396
+  match_type: contains
397
+  auto_fixed: shell_execution
398
+- name: '270. PIPELINE - BUILTIN ONLY: pipeline with :'
399
+  steps:
400
+  - send_line: ': | echo piped'
401
+  expect_output: piped
402
+  match_type: contains
403
+  auto_fixed: shell_execution
404
+- name: '271. PIPELINE - LONG CHAINS: 5-stage pipeline'
405
+  steps:
406
+  - send_line: echo test | cat | cat | cat | cat | cat
407
+  expect_output: test
408
+  match_type: contains
409
+- name: '271. PIPELINE - LONG CHAINS: pipeline with failures'
410
+  steps:
411
+  - send_line: echo ok | false | cat; echo $?
412
+  expect_output: '0'
413
+  match_type: contains
414
+  auto_fixed: shell_execution
415
+- name: '280. ALIAS - SPECIAL CASES: alias with quotes'
416
+  steps:
417
+  - send_line: alias greet='echo hello'; greet; unalias greet
418
+  expect_output: ''
419
+  match_type: exact
420
+- name: '280. ALIAS - SPECIAL CASES: alias with semicolon'
421
+  steps:
422
+  - send_line: alias both='echo a; echo b'; both; unalias both
423
+  expect_output: ''
424
+  match_type: exact
425
+- name: '280. ALIAS - SPECIAL CASES: alias -p format'
426
+  steps:
427
+  - send_line: alias foo=bar; alias -p | grep foo; unalias foo
428
+  expect_output: alias foo='bar'
429
+  match_type: contains
430
+  auto_fixed: shell_execution
431
+- name: '281. ALIAS - EXPANSION CONTEXT: alias in function'
432
+  steps:
433
+  - send_line: alias e=echo; f() { e test; }; f; unalias e
434
+  expect_output: ''
435
+  match_type: exact
436
+- name: '290. DOT - PATH HANDLING: dot with arguments'
437
+  steps:
438
+  - send_line: 'echo "echo sourced" > /tmp/src.sh; . /tmp/src.sh; rm /tmp/src.sh'
439
+  expect_output: 'sourced'
440
+  match_type: contains
441
+  auto_fixed: shell_execution
442
+- name: '290. DOT - PATH HANDLING: dot return value'
443
+  steps:
444
+  - send_line: echo "false" > /tmp/src.sh; . /tmp/src.sh; echo $?; rm /tmp/src.sh
445
+  expect_output: '1'
446
+  match_type: contains
447
+  auto_fixed: shell_execution
448
+- name: '290. DOT - PATH HANDLING: dot modifies vars'
449
+  steps:
450
+  - send_line: echo "X=modified" > /tmp/src.sh; X=original; . /tmp/src.sh; echo $X;
451
+      rm /tmp/src.sh
452
+  expect_output: modified
453
+  match_type: contains
454
+  auto_fixed: shell_execution
455
+- name: '300. SPECIAL BUILTINS - ERROR BEHAVIOR: break outside loop'
456
+  steps:
457
+  - send_line: (break 2>/dev/null); echo $?
458
+  expect_output: '0'
459
+  match_type: contains
460
+  auto_fixed: shell_execution
461
+- name: '300. SPECIAL BUILTINS - ERROR BEHAVIOR: continue outside loop'
462
+  steps:
463
+  - send_line: (continue 2>/dev/null); echo $?
464
+  expect_output: '0'
465
+  match_type: contains
466
+  auto_fixed: shell_execution
467
+- name: '300. SPECIAL BUILTINS - ERROR BEHAVIOR: colon with redirect'
468
+  steps:
469
+  - send_line: ': > /tmp/colon_test; test -f /tmp/colon_test && echo exists; rm /tmp/colon_test'
470
+  expect_output: exists
471
+  match_type: contains
472
+  auto_fixed: shell_execution
473
+- name: '310. ENVIRONMENT - PATH HANDLING: empty PATH component'
474
+  steps:
475
+  - send_line: echo "echo found" > /tmp/pathtest; chmod +x /tmp/pathtest; PATH="/tmp:$PATH"
476
+      pathtest; rm /tmp/pathtest
477
+  expect_output: found
478
+  match_type: contains
479
+  auto_fixed: shell_execution
480
+- name: '311. ENVIRONMENT - EXPORT BEHAVIOR: export in subshell'
481
+  steps:
482
+  - send_line: X=1; (export X=2); echo $X
483
+  expect_output: '1'
484
+  match_type: contains
485
+  auto_fixed: shell_execution
486
+- name: '311. ENVIRONMENT - EXPORT BEHAVIOR: export preserves'
487
+  steps:
488
+  - send_line: export X=1; X=2; sh -c "echo $X"
489
+  expect_output: '2'
490
+  match_type: contains
491
+  auto_fixed: shell_execution
492
+- name: '320. GLOB - SPECIAL FILENAMES: glob with spaces'
493
+  steps:
494
+  - send_line: mkdir -p /tmp/gt; touch "/tmp/gt/a b"; echo /tmp/gt/*; rm -r /tmp/gt
495
+  expect_output: /tmp/gt/a b
496
+  match_type: contains
497
+  auto_fixed: shell_execution
498
+- name: '320. GLOB - SPECIAL FILENAMES: glob no match'
499
+  steps:
500
+  - send_line: echo /nonexistent/path/*.xyz 2>/dev/null
501
+  expect_output: '/nonexistent/path/\*.xyz'
502
+  match_type: regex
503
+- name: '321. GLOB - CHARACTER CLASSES: glob [:alpha:]'
504
+  steps:
505
+  - send_line: mkdir -p /tmp/gc; touch /tmp/gc/a1 /tmp/gc/1a; echo /tmp/gc/[[:alpha:]]*;
506
+      rm -r /tmp/gc
507
+  expect_output: /tmp/gc/a1
508
+  match_type: contains
509
+  auto_fixed: shell_execution
510
+- name: '321. GLOB - CHARACTER CLASSES: glob [:digit:]'
511
+  steps:
512
+  - send_line: mkdir -p /tmp/gc; touch /tmp/gc/a1 /tmp/gc/1a; echo /tmp/gc/[[:digit:]]*;
513
+      rm -r /tmp/gc
514
+  expect_output: /tmp/gc/1a
515
+  match_type: contains
516
+  auto_fixed: shell_execution
517
+- name: '330. QUOTING - COMPLEX NESTING: quotes in command sub'
518
+  steps:
519
+  - send_line: echo "$(echo "inner")"
520
+  expect_output: inner
521
+  match_type: contains
522
+  auto_fixed: shell_execution
523
+- name: '330. QUOTING - COMPLEX NESTING: escaped quotes'
524
+  steps:
525
+  - send_line: echo "say \"hello\""
526
+  expect_output: say "hello"
527
+  match_type: contains
528
+- name: '330. QUOTING - COMPLEX NESTING: single in double'
529
+  steps:
530
+  - send_line: echo "it's fine"
531
+  expect_output: "it's fine"
532
+  match_type: contains
533
+- name: '330. QUOTING - COMPLEX NESTING: backslash in single'
534
+  steps:
535
+  - send_line: echo 'back\\slash'
536
+  expect_output: 'back\\\\slash'
537
+  match_type: regex
538
+- name: '331. QUOTING - EMPTY STRINGS: empty preserves arg'
539
+  steps:
540
+  - send_line: set -- "" "a"; echo $#
541
+  expect_output: '2'
542
+  match_type: contains
543
+  auto_fixed: shell_execution
544
+- name: '331. QUOTING - EMPTY STRINGS: unquoted empty gone'
545
+  steps:
546
+  - send_line: e=""; set -- $e a; echo $#
547
+  expect_output: '1'
548
+  match_type: contains
549
+  auto_fixed: shell_execution
550
+- name: '340. MISC - COMPOUND COMMANDS: if with compound cond'
551
+  steps:
552
+  - send_line: if true && true; then echo yes; fi
553
+  expect_output: 'yes'
554
+  match_type: contains
555
+  auto_fixed: shell_execution
556
+- name: '340. MISC - COMPOUND COMMANDS: while with pipeline cond'
557
+  steps:
558
+  - send_line: n=0; while echo $n | grep -q 0 && [ $n -lt 1 ]; do n=$((n+1)); done;
559
+      echo $n
560
+  expect_output: '1'
561
+  match_type: contains
562
+  auto_fixed: shell_execution
563
+- name: '341. MISC - COMPLEX COMBINATIONS: redirect in loop'
564
+  steps:
565
+  - send_line: for i in 1 2 3; do echo $i; done > /tmp/loop_out; cat /tmp/loop_out; rm /tmp/loop_out
566
+  expect_output: '1'
567
+  match_type: contains
568
+  auto_fixed: shell_execution
569
+- name: '341. MISC - COMPLEX COMBINATIONS: case with patterns'
570
+  steps:
571
+  - send_line: x=abc; case $x in a*) echo match;; esac
572
+  expect_output: match
573
+  match_type: contains
574
+  auto_fixed: shell_execution
suites/interactive/posix/posix_extended_auto.yamladded
@@ -0,0 +1,701 @@
1
+metadata:
2
+  category: Extended
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -e exists (exit code)'
8
+  steps:
9
+  - send_line: test -e /tmp/posix_test_regular
10
+  - send_line: echo "EXIT=$?"
11
+  expect_output: EXIT=1
12
+  match_type: contains
13
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -e nonexistent (exit code)'
14
+  steps:
15
+  - send_line: '! test -e /tmp/nonexistent_xyz_$$'
16
+  - send_line: echo "EXIT=$?"
17
+  expect_output: EXIT=0
18
+  match_type: contains
19
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -f regular file (exit code)'
20
+  steps:
21
+  - send_line: test -f /tmp/posix_test_regular
22
+  - send_line: echo "EXIT=$?"
23
+  expect_output: EXIT=1
24
+  match_type: contains
25
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -d directory (exit code)'
26
+  steps:
27
+  - send_line: test -d /tmp
28
+  - send_line: echo "EXIT=$?"
29
+  expect_output: EXIT=0
30
+  match_type: contains
31
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -s non-empty (exit code)'
32
+  steps:
33
+  - send_line: test -s /tmp/posix_test_nonempty
34
+  - send_line: echo "EXIT=$?"
35
+  expect_output: EXIT=1
36
+  match_type: contains
37
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -s empty (exit code)'
38
+  steps:
39
+  - send_line: '! test -s /tmp/posix_test_regular'
40
+  - send_line: echo "EXIT=$?"
41
+  expect_output: EXIT=0
42
+  match_type: contains
43
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -L symlink (exit code)'
44
+  steps:
45
+  - send_line: test -L /tmp/posix_test_symlink
46
+  - send_line: echo "EXIT=$?"
47
+  expect_output: EXIT=1
48
+  match_type: contains
49
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -h symlink (exit code)'
50
+  steps:
51
+  - send_line: test -h /tmp/posix_test_symlink
52
+  - send_line: echo "EXIT=$?"
53
+  expect_output: EXIT=1
54
+  match_type: contains
55
+- name: '26. EXTENDED TEST COMMAND - FILE TYPE TESTS: test -p fifo (exit code)'
56
+  steps:
57
+  - send_line: test -p /tmp/posix_test_fifo
58
+  - send_line: echo "EXIT=$?"
59
+  expect_output: EXIT=1
60
+  match_type: contains
61
+- name: '27. EXTENDED TEST COMMAND - FILE PERMISSION TESTS: test -r readable (exit
62
+    code)'
63
+  steps:
64
+  - send_line: test -r /tmp/posix_test_readable
65
+  - send_line: echo "EXIT=$?"
66
+  expect_output: EXIT=1
67
+  match_type: contains
68
+- name: '27. EXTENDED TEST COMMAND - FILE PERMISSION TESTS: test -w writable (exit
69
+    code)'
70
+  steps:
71
+  - send_line: test -w /tmp/posix_test_writable
72
+  - send_line: echo "EXIT=$?"
73
+  expect_output: EXIT=1
74
+  match_type: contains
75
+- name: '27. EXTENDED TEST COMMAND - FILE PERMISSION TESTS: test -x executable (exit
76
+    code)'
77
+  steps:
78
+  - send_line: test -x /tmp/posix_test_executable
79
+  - send_line: echo "EXIT=$?"
80
+  expect_output: EXIT=1
81
+  match_type: contains
82
+- name: '27. EXTENDED TEST COMMAND - FILE PERMISSION TESTS: test ! -x nonexec (exit
83
+    code)'
84
+  steps:
85
+  - send_line: '! test -x /tmp/posix_test_readable'
86
+  - send_line: echo "EXIT=$?"
87
+  expect_output: EXIT=0
88
+  match_type: contains
89
+- name: '28. EXTENDED TEST COMMAND - FILE COMPARISON: test -nt newer than (exit code)'
90
+  steps:
91
+  - send_line: test /tmp/posix_test_new -nt /tmp/posix_test_old
92
+  - send_line: echo "EXIT=$?"
93
+  expect_output: EXIT=1
94
+  match_type: contains
95
+- name: '28. EXTENDED TEST COMMAND - FILE COMPARISON: test -ot older than (exit code)'
96
+  steps:
97
+  - send_line: test /tmp/posix_test_old -ot /tmp/posix_test_new
98
+  - send_line: echo "EXIT=$?"
99
+  expect_output: EXIT=1
100
+  match_type: contains
101
+- name: '28. EXTENDED TEST COMMAND - FILE COMPARISON: test -ef same file (exit code)'
102
+  steps:
103
+  - send_line: test /tmp/posix_test_old -ef /tmp/posix_test_hardlink
104
+  - send_line: echo "EXIT=$?"
105
+  expect_output: EXIT=1
106
+  match_type: contains
107
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test -n nonempty string (exit code)'
108
+  steps:
109
+  - send_line: test -n 'hello'
110
+  - send_line: echo "EXIT=$?"
111
+  expect_output: EXIT=0
112
+  match_type: contains
113
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test -z empty string (exit code)'
114
+  steps:
115
+  - send_line: test -z ''
116
+  - send_line: echo "EXIT=$?"
117
+  expect_output: EXIT=0
118
+  match_type: contains
119
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test string = equal (exit code)'
120
+  steps:
121
+  - send_line: test 'abc' = 'abc'
122
+  - send_line: echo "EXIT=$?"
123
+  expect_output: EXIT=0
124
+  match_type: contains
125
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test string != not equal (exit
126
+    code)'
127
+  steps:
128
+  - send_line: test 'abc' != 'xyz'
129
+  - send_line: echo "EXIT=$?"
130
+  expect_output: EXIT=0
131
+  match_type: contains
132
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test unary string (exit code)'
133
+  steps:
134
+  - send_line: test 'hello'
135
+  - send_line: echo "EXIT=$?"
136
+  expect_output: EXIT=0
137
+  match_type: contains
138
+- name: '29. EXTENDED TEST COMMAND - STRING TESTS: test ! negation (exit code)'
139
+  steps:
140
+  - send_line: '! test -z ''hello'''
141
+  - send_line: echo "EXIT=$?"
142
+  expect_output: EXIT=0
143
+  match_type: contains
144
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -eq equal (exit code)'
145
+  steps:
146
+  - send_line: test 42 -eq 42
147
+  - send_line: echo "EXIT=$?"
148
+  expect_output: EXIT=0
149
+  match_type: contains
150
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -ne not equal (exit
151
+    code)'
152
+  steps:
153
+  - send_line: test 42 -ne 13
154
+  - send_line: echo "EXIT=$?"
155
+  expect_output: EXIT=0
156
+  match_type: contains
157
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -gt greater (exit code)'
158
+  steps:
159
+  - send_line: test 10 -gt 5
160
+  - send_line: echo "EXIT=$?"
161
+  expect_output: EXIT=0
162
+  match_type: contains
163
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -ge greater or equal
164
+    (exit code)'
165
+  steps:
166
+  - send_line: test 10 -ge 10
167
+  - send_line: echo "EXIT=$?"
168
+  expect_output: EXIT=0
169
+  match_type: contains
170
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -lt less (exit code)'
171
+  steps:
172
+  - send_line: test 5 -lt 10
173
+  - send_line: echo "EXIT=$?"
174
+  expect_output: EXIT=0
175
+  match_type: contains
176
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test -le less or equal (exit
177
+    code)'
178
+  steps:
179
+  - send_line: test 5 -le 5
180
+  - send_line: echo "EXIT=$?"
181
+  expect_output: EXIT=0
182
+  match_type: contains
183
+- name: '30. EXTENDED TEST COMMAND - INTEGER COMPARISON: test negative numbers (exit
184
+    code)'
185
+  steps:
186
+  - send_line: test -5 -lt 0
187
+  - send_line: echo "EXIT=$?"
188
+  expect_output: EXIT=0
189
+  match_type: contains
190
+- name: '31. EXTENDED TEST COMMAND - LOGICAL OPERATORS: test -a and (exit code)'
191
+  steps:
192
+  - send_line: test 5 -gt 3 -a 10 -gt 8
193
+  - send_line: echo "EXIT=$?"
194
+  expect_output: EXIT=0
195
+  match_type: contains
196
+- name: '31. EXTENDED TEST COMMAND - LOGICAL OPERATORS: test -o or (exit code)'
197
+  steps:
198
+  - send_line: test 5 -gt 10 -o 10 -gt 8
199
+  - send_line: echo "EXIT=$?"
200
+  expect_output: EXIT=0
201
+  match_type: contains
202
+- name: '31. EXTENDED TEST COMMAND - LOGICAL OPERATORS: test ! negation (exit code)'
203
+  steps:
204
+  - send_line: '! test 5 -gt 10'
205
+  - send_line: echo "EXIT=$?"
206
+  expect_output: EXIT=0
207
+  match_type: contains
208
+- name: '31. EXTENDED TEST COMMAND - LOGICAL OPERATORS: test ( ) grouping (exit code)'
209
+  steps:
210
+  - send_line: test \( 5 -gt 3 \) -a \( 10 -gt 8 \)
211
+  - send_line: echo "EXIT=$?"
212
+  expect_output: EXIT=0
213
+  match_type: contains
214
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: use default unset'
215
+  steps:
216
+  - send_line: unset VAR; echo "${VAR-default}"
217
+  expect_output: default
218
+  match_type: contains
219
+  auto_fixed: shell_execution
220
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: use default null'
221
+  steps:
222
+  - send_line: VAR=; echo "${VAR-default}"
223
+  expect_output: ''
224
+  match_type: contains
225
+  auto_fixed: manual_determination
226
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: use default null colon'
227
+  steps:
228
+  - send_line: VAR=; echo "${VAR:-default}"
229
+  expect_output: default
230
+  match_type: contains
231
+  auto_fixed: shell_execution
232
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: use default set'
233
+  steps:
234
+  - send_line: VAR=value; echo "${VAR-default}"
235
+  expect_output: value
236
+  match_type: contains
237
+  auto_fixed: shell_execution
238
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: assign default unset'
239
+  steps:
240
+  - send_line: unset VAR; echo "${VAR=assigned}"; echo $VAR
241
+  expect_output: assigned
242
+  match_type: contains
243
+- name: '32. EXTENDED PARAMETER EXPANSION - DEFAULT VALUES: assign default null colon'
244
+  steps:
245
+  - send_line: VAR=; echo "${VAR:=assigned}"; echo $VAR
246
+  expect_output: assigned
247
+  match_type: contains
248
+- name: '33. EXTENDED PARAMETER EXPANSION - ERROR IF UNSET: no error if set'
249
+  steps:
250
+  - send_line: VAR=value; echo "${VAR?error}"
251
+  expect_output: value
252
+  match_type: contains
253
+  auto_fixed: shell_execution
254
+- name: '34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE: alt unset'
255
+  steps:
256
+  - send_line: unset VAR; echo "${VAR+alternative}"
257
+  expect_output: ''
258
+  match_type: contains
259
+  auto_fixed: manual_determination
260
+- name: '34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE: alt null'
261
+  steps:
262
+  - send_line: VAR=; echo "${VAR+alternative}"
263
+  expect_output: alternative
264
+  match_type: contains
265
+  auto_fixed: shell_execution
266
+- name: '34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE: alt null colon'
267
+  steps:
268
+  - send_line: VAR=; echo "${VAR:+alternative}"
269
+  expect_output: ''
270
+  match_type: contains
271
+  auto_fixed: manual_determination
272
+- name: '34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE: alt set'
273
+  steps:
274
+  - send_line: VAR=value; echo "${VAR+alternative}"
275
+  expect_output: alternative
276
+  match_type: contains
277
+  auto_fixed: shell_execution
278
+- name: '34. EXTENDED PARAMETER EXPANSION - ALTERNATIVE VALUE: alt set colon'
279
+  steps:
280
+  - send_line: VAR=value; echo "${VAR:+alternative}"
281
+  expect_output: alternative
282
+  match_type: contains
283
+  auto_fixed: shell_execution
284
+- name: '35. EXTENDED PARAMETER EXPANSION - STRING LENGTH: length empty'
285
+  steps:
286
+  - send_line: VAR=; echo "${#VAR}"
287
+  expect_output: '0'
288
+  match_type: contains
289
+  auto_fixed: shell_execution
290
+- name: '35. EXTENDED PARAMETER EXPANSION - STRING LENGTH: length short'
291
+  steps:
292
+  - send_line: VAR=hi; echo "${#VAR}"
293
+  expect_output: '2'
294
+  match_type: contains
295
+- name: '35. EXTENDED PARAMETER EXPANSION - STRING LENGTH: length long'
296
+  steps:
297
+  - send_line: VAR="hello world"; echo "${#VAR}"
298
+  expect_output: '11'
299
+  match_type: contains
300
+- name: '35. EXTENDED PARAMETER EXPANSION - STRING LENGTH: length special chars'
301
+  steps:
302
+  - send_line: VAR="a b c"; echo "${#VAR}"
303
+  expect_output: '5'
304
+  match_type: contains
305
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix # simple'
306
+  steps:
307
+  - send_line: VAR=hello; echo "${VAR#hel}"
308
+  expect_output: lo
309
+  match_type: contains
310
+  auto_fixed: shell_execution
311
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix # nomatch'
312
+  steps:
313
+  - send_line: VAR=hello; echo "${VAR#xyz}"
314
+  expect_output: hello
315
+  match_type: contains
316
+  auto_fixed: shell_execution
317
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix # glob'
318
+  steps:
319
+  - send_line: VAR=foo.bar.baz; echo "${VAR#*.}"
320
+  expect_output: bar.baz
321
+  match_type: contains
322
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix ## glob'
323
+  steps:
324
+  - send_line: VAR=foo.bar.baz; echo "${VAR##*.}"
325
+  expect_output: baz
326
+  match_type: contains
327
+  auto_fixed: shell_execution
328
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix # star'
329
+  steps:
330
+  - send_line: VAR=/usr/local/bin; echo "${VAR#*/}"
331
+  expect_output: usr/local/bin
332
+  match_type: contains
333
+  auto_fixed: shell_execution
334
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: prefix ## star'
335
+  steps:
336
+  - send_line: VAR=/usr/local/bin; echo "${VAR##*/}"
337
+  expect_output: bin
338
+  match_type: contains
339
+  auto_fixed: shell_execution
340
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix % simple'
341
+  steps:
342
+  - send_line: VAR=hello; echo "${VAR%lo}"
343
+  expect_output: hel
344
+  match_type: contains
345
+  auto_fixed: shell_execution
346
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix % nomatch'
347
+  steps:
348
+  - send_line: VAR=hello; echo "${VAR%xyz}"
349
+  expect_output: hello
350
+  match_type: contains
351
+  auto_fixed: shell_execution
352
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix % glob'
353
+  steps:
354
+  - send_line: VAR=foo.bar.baz; echo "${VAR%.*}"
355
+  expect_output: foo.bar
356
+  match_type: contains
357
+  auto_fixed: shell_execution
358
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix %% glob'
359
+  steps:
360
+  - send_line: VAR=foo.bar.baz; echo "${VAR%%.*}"
361
+  expect_output: foo
362
+  match_type: contains
363
+  auto_fixed: shell_execution
364
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix % extension'
365
+  steps:
366
+  - send_line: VAR=file.tar.gz; echo "${VAR%.gz}"
367
+  expect_output: file.tar
368
+  match_type: contains
369
+  auto_fixed: shell_execution
370
+- name: '36. EXTENDED PARAMETER EXPANSION - PATTERN REMOVAL: suffix %% extension'
371
+  steps:
372
+  - send_line: VAR=file.tar.gz; echo "${VAR%%.*}"
373
+  expect_output: file
374
+  match_type: contains
375
+  auto_fixed: shell_execution
376
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith addition'
377
+  steps:
378
+  - send_line: echo $((5 + 3))
379
+  expect_output: '8'
380
+  match_type: contains
381
+  auto_fixed: shell_execution
382
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith subtraction'
383
+  steps:
384
+  - send_line: echo $((10 - 4))
385
+  expect_output: '6'
386
+  match_type: contains
387
+  auto_fixed: shell_execution
388
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith multiplication'
389
+  steps:
390
+  - send_line: echo $((6 * 7))
391
+  expect_output: '42'
392
+  match_type: contains
393
+  auto_fixed: shell_execution
394
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith division'
395
+  steps:
396
+  - send_line: echo $((20 / 4))
397
+  expect_output: '5'
398
+  match_type: contains
399
+  auto_fixed: shell_execution
400
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith modulo'
401
+  steps:
402
+  - send_line: echo $((17 % 5))
403
+  expect_output: '2'
404
+  match_type: contains
405
+  auto_fixed: shell_execution
406
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith negative'
407
+  steps:
408
+  - send_line: echo $((-5 + 10))
409
+  expect_output: '5'
410
+  match_type: contains
411
+  auto_fixed: shell_execution
412
+- name: '37. ARITHMETIC EXPANSION - BASIC OPERATIONS: arith zero'
413
+  steps:
414
+  - send_line: echo $((0 + 0))
415
+  expect_output: '0'
416
+  match_type: contains
417
+  auto_fixed: shell_execution
418
+- name: '38. ARITHMETIC EXPANSION - PRECEDENCE: arith precedence mult'
419
+  steps:
420
+  - send_line: echo $((2 + 3 * 4))
421
+  expect_output: '14'
422
+  match_type: contains
423
+  auto_fixed: shell_execution
424
+- name: '38. ARITHMETIC EXPANSION - PRECEDENCE: arith precedence paren'
425
+  steps:
426
+  - send_line: echo $(((2 + 3) * 4))
427
+  expect_output: '20'
428
+  match_type: contains
429
+  auto_fixed: shell_execution
430
+- name: '38. ARITHMETIC EXPANSION - PRECEDENCE: arith precedence div'
431
+  steps:
432
+  - send_line: echo $((10 - 8 / 2))
433
+  expect_output: '6'
434
+  match_type: contains
435
+  auto_fixed: shell_execution
436
+- name: '38. ARITHMETIC EXPANSION - PRECEDENCE: arith precedence complex'
437
+  steps:
438
+  - send_line: echo $((2 * 3 + 4 * 5))
439
+  expect_output: '26'
440
+  match_type: contains
441
+  auto_fixed: shell_execution
442
+- name: '39. ARITHMETIC EXPANSION - VARIABLES: arith var'
443
+  steps:
444
+  - send_line: X=5; echo $((X + 3))
445
+  expect_output: '8'
446
+  match_type: contains
447
+  auto_fixed: shell_execution
448
+- name: '39. ARITHMETIC EXPANSION - VARIABLES: arith var no dollar'
449
+  steps:
450
+  - send_line: X=10; Y=20; echo $((X + Y))
451
+  expect_output: '30'
452
+  match_type: contains
453
+  auto_fixed: shell_execution
454
+- name: '39. ARITHMETIC EXPANSION - VARIABLES: arith var assign'
455
+  steps:
456
+  - send_line: X=5; Y=$((X * 2)); echo $Y
457
+  expect_output: '10'
458
+  match_type: contains
459
+  auto_fixed: shell_execution
460
+- name: '39. ARITHMETIC EXPANSION - VARIABLES: arith var complex'
461
+  steps:
462
+  - send_line: A=3; B=4; echo $((A * A + B * B))
463
+  expect_output: '25'
464
+  match_type: contains
465
+  auto_fixed: shell_execution
466
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare eq true'
467
+  steps:
468
+  - send_line: echo $((5 == 5))
469
+  expect_output: '1'
470
+  match_type: contains
471
+  auto_fixed: shell_execution
472
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare eq false'
473
+  steps:
474
+  - send_line: echo $((5 == 3))
475
+  expect_output: '0'
476
+  match_type: contains
477
+  auto_fixed: shell_execution
478
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare ne true'
479
+  steps:
480
+  - send_line: echo $((5 != 3))
481
+  expect_output: '1'
482
+  match_type: contains
483
+  auto_fixed: shell_execution
484
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare ne false'
485
+  steps:
486
+  - send_line: echo $((5 != 5))
487
+  expect_output: '0'
488
+  match_type: contains
489
+  auto_fixed: shell_execution
490
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare lt'
491
+  steps:
492
+  - send_line: echo $((3 < 5))
493
+  expect_output: '1'
494
+  match_type: contains
495
+  auto_fixed: shell_execution
496
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare le'
497
+  steps:
498
+  - send_line: echo $((5 <= 5))
499
+  expect_output: '1'
500
+  match_type: contains
501
+  auto_fixed: shell_execution
502
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare gt'
503
+  steps:
504
+  - send_line: echo $((7 > 5))
505
+  expect_output: '1'
506
+  match_type: contains
507
+  auto_fixed: shell_execution
508
+- name: '40. ARITHMETIC EXPANSION - COMPARISON: arith compare ge'
509
+  steps:
510
+  - send_line: echo $((5 >= 5))
511
+  expect_output: '1'
512
+  match_type: contains
513
+  auto_fixed: shell_execution
514
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical and true'
515
+  steps:
516
+  - send_line: echo $((1 && 1))
517
+  expect_output: '1'
518
+  match_type: contains
519
+  auto_fixed: shell_execution
520
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical and false'
521
+  steps:
522
+  - send_line: echo $((1 && 0))
523
+  expect_output: '0'
524
+  match_type: contains
525
+  auto_fixed: shell_execution
526
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical or true'
527
+  steps:
528
+  - send_line: echo $((0 || 1))
529
+  expect_output: '1'
530
+  match_type: contains
531
+  auto_fixed: shell_execution
532
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical or false'
533
+  steps:
534
+  - send_line: echo $((0 || 0))
535
+  expect_output: '0'
536
+  match_type: contains
537
+  auto_fixed: shell_execution
538
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical not true'
539
+  steps:
540
+  - send_line: echo $((! 0))
541
+  expect_output: '1'
542
+  match_type: contains
543
+  auto_fixed: shell_execution
544
+- name: '41. ARITHMETIC EXPANSION - LOGICAL: arith logical not false'
545
+  steps:
546
+  - send_line: echo $((! 1))
547
+  expect_output: '0'
548
+  match_type: contains
549
+  auto_fixed: shell_execution
550
+- name: '42. SPECIAL PARAMETERS: \$\$ process id type'
551
+  steps:
552
+  - send_line: echo $$ | grep -c "^[0-9][0-9]*$"
553
+  expect_output: '1'
554
+  match_type: contains
555
+  auto_fixed: shell_execution
556
+- name: '42. SPECIAL PARAMETERS: \$- shell flags type'
557
+  steps:
558
+  - send_line: echo $- | grep -c '[a-z]'
559
+  expect_output: '1'
560
+  match_type: contains
561
+- name: '42. SPECIAL PARAMETERS: \$# arg count'
562
+  steps:
563
+  - send_line: set -- a b c; echo $#
564
+  expect_output: '3'
565
+  match_type: contains
566
+  auto_fixed: shell_execution
567
+- name: '42. SPECIAL PARAMETERS: \$1 first arg'
568
+  steps:
569
+  - send_line: set -- first second; echo $1
570
+  expect_output: first
571
+  match_type: contains
572
+  auto_fixed: shell_execution
573
+- name: '42. SPECIAL PARAMETERS: \$2 second arg'
574
+  steps:
575
+  - send_line: set -- first second; echo $2
576
+  expect_output: second
577
+  match_type: contains
578
+  auto_fixed: shell_execution
579
+- name: '42. SPECIAL PARAMETERS: \$9 ninth arg'
580
+  steps:
581
+  - send_line: set -- a b c d e f g h i j; echo $9
582
+  expect_output: i
583
+  match_type: contains
584
+  auto_fixed: shell_execution
585
+- name: '42. SPECIAL PARAMETERS: \$* all args'
586
+  steps:
587
+  - send_line: set -- a b c; echo $*
588
+  expect_output: a b c
589
+  match_type: contains
590
+  auto_fixed: shell_execution
591
+- name: '42. SPECIAL PARAMETERS: \$@ all args'
592
+  steps:
593
+  - send_line: set -- a b c; echo $@
594
+  expect_output: a b c
595
+  match_type: contains
596
+  auto_fixed: shell_execution
597
+- name: '43. ADDITIONAL POSIX BUILTINS - CD/PWD: cd to /tmp'
598
+  steps:
599
+  - send_line: cd /tmp && pwd
600
+  expect_output: /tmp
601
+  match_type: contains
602
+  auto_fixed: shell_execution
603
+- name: '43. ADDITIONAL POSIX BUILTINS - CD/PWD: cd relative'
604
+  steps:
605
+  - send_line: cd /tmp && cd .. && pwd | grep -c "^/"
606
+  expect_output: '1'
607
+  match_type: contains
608
+- name: '43. ADDITIONAL POSIX BUILTINS - CD/PWD: cd $HOME'
609
+  steps:
610
+  - send_line: cd && pwd | grep -c "^/"
611
+  expect_output: '1'
612
+  match_type: contains
613
+- name: '44. ADDITIONAL POSIX BUILTINS - UNSET: unset variable'
614
+  steps:
615
+  - send_line: VAR=test; unset VAR; echo ${VAR:-unset}
616
+  expect_output: unset
617
+  match_type: contains
618
+  auto_fixed: shell_execution
619
+- name: '44. ADDITIONAL POSIX BUILTINS - UNSET: unset nonexistent'
620
+  steps:
621
+  - send_line: unset NONEXISTENT_VAR_XYZ; echo ok
622
+  expect_output: ok
623
+  match_type: contains
624
+- name: '45. ADDITIONAL POSIX BUILTINS - EVAL: eval simple'
625
+  steps:
626
+  - send_line: CMD="echo hello"; eval $CMD
627
+  expect_output: hello
628
+  match_type: contains
629
+  auto_fixed: shell_execution
630
+- name: '45. ADDITIONAL POSIX BUILTINS - EVAL: eval with var'
631
+  steps:
632
+  - send_line: X=5; CMD="echo $X"; eval $CMD
633
+  expect_output: '5'
634
+  match_type: contains
635
+  auto_fixed: shell_execution
636
+- name: '45. ADDITIONAL POSIX BUILTINS - EVAL: eval complex'
637
+  steps:
638
+  - send_line: A=echo; B=test; eval $A $B
639
+  expect_output: test
640
+  match_type: contains
641
+  auto_fixed: shell_execution
642
+- name: '46. ADDITIONAL POSIX BUILTINS - COLON: : null command'
643
+  steps:
644
+  - send_line: ': ; echo ok'
645
+  expect_output: ok
646
+  match_type: contains
647
+- name: '46. ADDITIONAL POSIX BUILTINS - COLON: : with args'
648
+  steps:
649
+  - send_line: ': this is ignored; echo ok'
650
+  expect_output: ok
651
+  match_type: contains
652
+- name: '47. TILDE EXPANSION: tilde home'
653
+  steps:
654
+  - send_line: echo ~ | grep -c "^/"
655
+  expect_output: '1'
656
+  match_type: contains
657
+- name: '47. TILDE EXPANSION: tilde in path'
658
+  steps:
659
+  - send_line: echo ~/test | grep -c "^/"
660
+  expect_output: '1'
661
+  match_type: contains
662
+- name: '48. FIELD SPLITTING - ADVANCED: IFS multiple fields'
663
+  steps:
664
+  - send_line: IFS=:; VAR="a:b:c:d"; set -- $VAR; echo $# $1 $4
665
+  expect_output: 4 a d
666
+  match_type: contains
667
+  auto_fixed: shell_execution
668
+- name: '48. FIELD SPLITTING - ADVANCED: IFS whitespace'
669
+  steps:
670
+  - send_line: IFS=" "; VAR="a b c"; set -- $VAR; echo $#
671
+  expect_output: '3'
672
+  match_type: contains
673
+  auto_fixed: shell_execution
674
+- name: '48. FIELD SPLITTING - ADVANCED: IFS comma'
675
+  steps:
676
+  - send_line: IFS=,; VAR="x,y,z"; set -- $VAR; echo $2
677
+  expect_output: y
678
+  match_type: contains
679
+  auto_fixed: shell_execution
680
+- name: '49. BACKGROUND JOBS: background exit'
681
+  steps:
682
+  - send_line: (exit 0) & wait $!; echo $?
683
+  expect_output: '0'
684
+  match_type: contains
685
+  auto_fixed: shell_execution
686
+- name: '50. COMMAND GROUPING: subshell isolation'
687
+  steps:
688
+  - send_line: X=1; (X=2; echo $X); echo $X
689
+  expect_output: '2'
690
+  match_type: contains
691
+- name: '50. COMMAND GROUPING: brace grouping'
692
+  steps:
693
+  - send_line: X=1; { X=2; echo $X; }; echo $X
694
+  expect_output: '2'
695
+  match_type: contains
696
+- name: '50. COMMAND GROUPING: subshell exit'
697
+  steps:
698
+  - send_line: (exit 5); echo $?
699
+  expect_output: '5'
700
+  match_type: contains
701
+  auto_fixed: shell_execution
suites/interactive/posix/posix_gaps_auto.yamladded
@@ -0,0 +1,960 @@
1
+metadata:
2
+  category: Gaps
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '92. REDIRECTION OPERATOR <> (READ/WRITE): redirect <> creates file (exit
8
+    code)'
9
+  steps:
10
+  - send_line: echo test <> /tmp/posix_gaps_rw_$$; test -f /tmp/posix_gaps_rw_$$;
11
+      rm -f /tmp/posix_gaps_rw_$$
12
+  - send_line: echo "EXIT=$?"
13
+  expect_output: EXIT=0
14
+  match_type: contains
15
+- name: '92. REDIRECTION OPERATOR <> (READ/WRITE): redirect <> opens existing (exit
16
+    code)'
17
+  steps:
18
+  - send_line: echo data > /tmp/posix_gaps_rw2_$$; cat <> /tmp/posix_gaps_rw2_$$ 2>/dev/null;
19
+      rm -f /tmp/posix_gaps_rw2_$$
20
+  - send_line: echo "EXIT=$?"
21
+  expect_output: EXIT=0
22
+  match_type: contains
23
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS mixed ws and non-ws'
24
+  steps:
25
+  - send_line: 'IFS='': \t''; VAR=''a:b c:d''; set -- $VAR; echo $# $1 $2 $3 $4'
26
+  expect_output: '4'
27
+  match_type: contains
28
+  auto_fixed: shell_execution
29
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS multiple delimiters'
30
+  steps:
31
+  - send_line: IFS=',:'; VAR='a,b:c,d'; set -- $VAR; echo $#
32
+  expect_output: '4'
33
+  match_type: contains
34
+  auto_fixed: shell_execution
35
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS trailing delimiters'
36
+  steps:
37
+  - send_line: IFS=:; VAR='a:b:c:'; set -- $VAR; echo $#
38
+  expect_output: '3'
39
+  match_type: contains
40
+  auto_fixed: shell_execution
41
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS leading and trailing'
42
+  steps:
43
+  - send_line: IFS=:; VAR=':a:b:'; set -- $VAR; echo $# $1 $2
44
+  expect_output: '3'
45
+  match_type: contains
46
+  auto_fixed: shell_execution
47
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS consecutive delimiters'
48
+  steps:
49
+  - send_line: IFS=:; VAR='a::b'; set -- $VAR; echo $# $1 $2 $3
50
+  expect_output: '3'
51
+  match_type: contains
52
+  auto_fixed: shell_execution
53
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS whitespace collapsing'
54
+  steps:
55
+  - send_line: IFS=' '; VAR='a  b   c'; set -- $VAR; echo $#
56
+  expect_output: '3'
57
+  match_type: contains
58
+  auto_fixed: shell_execution
59
+- name: '93. COMPLEX IFS FIELD SPLITTING: IFS null splits nothing'
60
+  steps:
61
+  - send_line: IFS=''; VAR='a b c'; set -- $VAR; echo $#
62
+  expect_output: '1'
63
+  match_type: contains
64
+  auto_fixed: shell_execution
65
+- name: '94. NESTED PARAMETER EXPANSION: nested default expansion'
66
+  steps:
67
+  - send_line: unset A; B=inner; echo ${A:-${B}}
68
+  expect_output: inner
69
+  match_type: contains
70
+  auto_fixed: shell_execution
71
+- name: '94. NESTED PARAMETER EXPANSION: nested length expansion'
72
+  steps:
73
+  - send_line: VAR=hello; echo ${#VAR}
74
+  expect_output: '5'
75
+  match_type: contains
76
+  auto_fixed: shell_execution
77
+- name: '94. NESTED PARAMETER EXPANSION: nested pattern removal'
78
+  steps:
79
+  - send_line: VAR=/usr/local/bin; echo ${VAR#${VAR%/*}}
80
+  expect_output: /bin
81
+  match_type: contains
82
+  auto_fixed: shell_execution
83
+- name: '94. NESTED PARAMETER EXPANSION: multiple parameter expansions'
84
+  steps:
85
+  - send_line: A=foo; B=bar; echo ${A}${B}
86
+  expect_output: foobar
87
+  match_type: contains
88
+  auto_fixed: shell_execution
89
+- name: '94. NESTED PARAMETER EXPANSION: nested with quotes'
90
+  steps:
91
+  - send_line: A='a b'; echo "${A:-default}"
92
+  expect_output: a b
93
+  match_type: contains
94
+- name: '95. COMMAND NAME RESOLUTION ORDER: function overrides echo'
95
+  steps:
96
+  - send_line: echo() { printf 'function\n'; }; echo test | grep -c function
97
+  expect_output: '1'
98
+  match_type: contains
99
+- name: '95. COMMAND NAME RESOLUTION ORDER: command -v finds function'
100
+  steps:
101
+  - send_line: func() { :; }; command -v func | grep -c func
102
+  expect_output: '[0-9]+'
103
+  match_type: regex
104
+- name: '95. COMMAND NAME RESOLUTION ORDER: command bypasses function'
105
+  steps:
106
+  - send_line: echo() { printf 'func\n'; }; command echo test
107
+  expect_output: test
108
+  match_type: contains
109
+  auto_fixed: shell_execution
110
+- name: '95. COMMAND NAME RESOLUTION ORDER: unset function reveals builtin'
111
+  steps:
112
+  - send_line: echo() { printf 'f\n'; }; unset -f echo; echo test | grep -c test
113
+  expect_output: '1'
114
+  match_type: contains
115
+- name: '96. COMPLEX QUOTING AND ESCAPING: backslash in double quotes'
116
+  steps:
117
+  - send_line: echo "test\\nword"
118
+  expect_output: test\\nword
119
+  match_type: contains
120
+- name: '96. COMPLEX QUOTING AND ESCAPING: dollar in double quotes'
121
+  steps:
122
+  - send_line: "echo 'price: $5'"
123
+  expect_output: 'price:'
124
+  match_type: contains
125
+- name: '96. COMPLEX QUOTING AND ESCAPING: backtick in double quotes'
126
+  steps:
127
+  - send_line: 'echo "date: `date +%Y`" | grep -c date'
128
+  expect_output: '1'
129
+  match_type: contains
130
+- name: '96. COMPLEX QUOTING AND ESCAPING: mixed quoting'
131
+  steps:
132
+  - send_line: echo 'single'"double"
133
+  expect_output: singledouble
134
+  match_type: contains
135
+- name: '96. COMPLEX QUOTING AND ESCAPING: empty quotes concatenation'
136
+  steps:
137
+  - send_line: echo ''test''
138
+  expect_output: test
139
+  match_type: contains
140
+- name: '96. COMPLEX QUOTING AND ESCAPING: quote removal'
141
+  steps:
142
+  - send_line: VAR="\"test\""; echo $VAR
143
+  expect_output: '"test"'
144
+  match_type: contains
145
+- name: '97. PIPELINE EXIT STATUS: pipeline last command status (exit code)'
146
+  steps:
147
+  - send_line: true | true | false
148
+  - send_line: echo "EXIT=$?"
149
+  expect_output: EXIT=1
150
+  match_type: contains
151
+- name: '97. PIPELINE EXIT STATUS: pipeline first fails (exit code)'
152
+  steps:
153
+  - send_line: false | true | true
154
+  - send_line: echo "EXIT=$?"
155
+  expect_output: EXIT=0
156
+  match_type: contains
157
+- name: '97. PIPELINE EXIT STATUS: pipeline middle fails (exit code)'
158
+  steps:
159
+  - send_line: true | false | true
160
+  - send_line: echo "EXIT=$?"
161
+  expect_output: EXIT=0
162
+  match_type: contains
163
+- name: '97. PIPELINE EXIT STATUS: PIPESTATUS concept'
164
+  steps:
165
+  - send_line: false | true | true; echo $?
166
+  expect_output: '0'
167
+  match_type: contains
168
+  auto_fixed: shell_execution
169
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic negative numbers'
170
+  steps:
171
+  - send_line: echo $((-5 * -3))
172
+  expect_output: '15'
173
+  match_type: contains
174
+  auto_fixed: shell_execution
175
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic large numbers'
176
+  steps:
177
+  - send_line: echo $((999999 + 1))
178
+  expect_output: '1000000'
179
+  match_type: contains
180
+  auto_fixed: shell_execution
181
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic modulo negative'
182
+  steps:
183
+  - send_line: echo $((-17 % 5))
184
+  expect_output: '-2'
185
+  match_type: contains
186
+  auto_fixed: shell_execution
187
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic nested parens'
188
+  steps:
189
+  - send_line: echo $(((2 + 3) * (4 + 5)))
190
+  expect_output: '45'
191
+  match_type: contains
192
+  auto_fixed: shell_execution
193
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic comparison chain'
194
+  steps:
195
+  - send_line: echo $((5 > 3 && 10 > 8))
196
+  expect_output: '1'
197
+  match_type: contains
198
+  auto_fixed: shell_execution
199
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic unary minus'
200
+  steps:
201
+  - send_line: X=5; echo $((-X))
202
+  expect_output: '-5'
203
+  match_type: contains
204
+  auto_fixed: shell_execution
205
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic unary plus'
206
+  steps:
207
+  - send_line: X=5; echo $((+X))
208
+  expect_output: '5'
209
+  match_type: contains
210
+  auto_fixed: shell_execution
211
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic octal numbers'
212
+  steps:
213
+  - send_line: echo $((010))
214
+  expect_output: '8'
215
+  match_type: contains
216
+  auto_fixed: shell_execution
217
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic hex numbers'
218
+  steps:
219
+  - send_line: echo $((0x10))
220
+  expect_output: '16'
221
+  match_type: contains
222
+  auto_fixed: shell_execution
223
+- name: '98. COMPLEX ARITHMETIC EDGE CASES: arithmetic division by zero (exit code)'
224
+  steps:
225
+  - send_line: echo $((5 / 0)) 2>/dev/null
226
+  - send_line: echo "EXIT=$?"
227
+  expect_output: EXIT=1
228
+  match_type: contains
229
+- name: '99. PATHNAME EXPANSION EDGE CASES: glob bracket literal'
230
+  steps:
231
+  - send_line: ls /tmp/posix_gaps_test_glob/file[[]3].txt 2>/dev/null | wc -l
232
+  expect_output: '[0-9]+'
233
+  match_type: regex
234
+- name: '99. PATHNAME EXPANSION EDGE CASES: glob dash in bracket'
235
+  steps:
236
+  - send_line: ls /tmp/posix_gaps_test_glob/[-a-z]file.txt 2>/dev/null | wc -l
237
+  expect_output: '[0-9]+'
238
+  match_type: regex
239
+- name: '99. PATHNAME EXPANSION EDGE CASES: glob no match returns literal'
240
+  steps:
241
+  - send_line: echo /tmp/posix_gaps_test_glob/*.xyz | grep -c '\*'
242
+  expect_output: '1'
243
+  match_type: contains
244
+- name: '99. PATHNAME EXPANSION EDGE CASES: glob hidden dirs'
245
+  steps:
246
+  - send_line: ls -d /tmp/posix_gaps_test_glob/.* 2>/dev/null | grep -c hidden
247
+  expect_output: '[0-9]+'
248
+  match_type: regex
249
+- name: '99. PATHNAME EXPANSION EDGE CASES: glob character class digit'
250
+  steps:
251
+  - send_line: touch /tmp/posix_gaps_test_glob/f1.txt; ls /tmp/posix_gaps_test_glob/f[[:digit:]].txt
252
+      2>/dev/null | wc -l
253
+  expect_output: '[0-9]+'
254
+  match_type: regex
255
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function local scope via subshell'
256
+  steps:
257
+  - send_line: f() { (X=inner; echo $X); }; X=outer; f; echo $X
258
+  expect_output: inner
259
+  match_type: contains
260
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function positional params'
261
+  steps:
262
+  - send_line: f() { echo $1 $2; }; set -- a b; f x y
263
+  expect_output: x y
264
+  match_type: contains
265
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function preserves positional'
266
+  steps:
267
+  - send_line: f() { echo $1; }; set -- a b; f x; echo $1
268
+  expect_output: 'x'
269
+  match_type: contains
270
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: nested function calls'
271
+  steps:
272
+  - send_line: a() { b; }; b() { c; }; c() { echo deep; }; a
273
+  expect_output: deep
274
+  match_type: contains
275
+  auto_fixed: shell_execution
276
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: function return in subshell'
277
+  steps:
278
+  - send_line: f() { (return 5); echo $?; }; f
279
+  expect_output: '5'
280
+  match_type: contains
281
+- name: '100. FUNCTION SCOPE AND RECURSION EDGE CASES: recursive factorial'
282
+  steps:
283
+  - send_line: fact() { if [ $1 -le 1 ]; then echo 1; else local r=$(fact $(($1-1))
284
+      2>/dev/null || fact $(($1-1))); echo $(($1 * r)); fi; }; fact 4
285
+  expect_output: '24'
286
+  match_type: contains
287
+  auto_fixed: shell_execution
288
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: subshell exit status (exit code)'
289
+  steps:
290
+  - send_line: (exit 42); echo $?
291
+  - send_line: echo "EXIT=$?"
292
+  expect_output: EXIT=0
293
+  match_type: contains
294
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: brace group exit status (exit code)'
295
+  steps:
296
+  - send_line: '{ false; }; echo $?'
297
+  - send_line: echo "EXIT=$?"
298
+  expect_output: EXIT=0
299
+  match_type: contains
300
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: if statement exit status (exit code)'
301
+  steps:
302
+  - send_line: if true; then true; fi; echo $?
303
+  - send_line: echo "EXIT=$?"
304
+  expect_output: EXIT=0
305
+  match_type: contains
306
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: for loop exit status (exit code)'
307
+  steps:
308
+  - send_line: for i in 1; do false; done; echo $?
309
+  - send_line: echo "EXIT=$?"
310
+  expect_output: EXIT=0
311
+  match_type: contains
312
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: while loop exit status (exit code)'
313
+  steps:
314
+  - send_line: while false; do :; done; echo $?
315
+  - send_line: echo "EXIT=$?"
316
+  expect_output: EXIT=0
317
+  match_type: contains
318
+- name: '101. EXIT STATUS IN COMPOUND COMMANDS: case exit status (exit code)'
319
+  steps:
320
+  - send_line: case x in x) false;; esac; echo $?
321
+  - send_line: echo "EXIT=$?"
322
+  expect_output: EXIT=0
323
+  match_type: contains
324
+- name: '102. SET BUILTIN EDGE CASES: set -- clears positionals'
325
+  steps:
326
+  - send_line: set -- a b; set --; echo $#
327
+  expect_output: '0'
328
+  match_type: contains
329
+- name: '102. SET BUILTIN EDGE CASES: set -- with empty'
330
+  steps:
331
+  - send_line: set -- ''; echo $# |$1|
332
+  expect_output: 1 ||
333
+  match_type: contains
334
+  auto_fixed: manual_determination
335
+- name: '102. SET BUILTIN EDGE CASES: set -- with spaces'
336
+  steps:
337
+  - send_line: set -- 'a b' 'c d'; echo $1
338
+  expect_output: '''a'
339
+  match_type: contains
340
+  auto_fixed: shell_execution
341
+- name: '102. SET BUILTIN EDGE CASES: set without args shows vars'
342
+  steps:
343
+  - send_line: X=1; set | grep -c '^X='
344
+  expect_output: '[0-9]+'
345
+  match_type: regex
346
+- name: '102. SET BUILTIN EDGE CASES: set -o lists options'
347
+  steps:
348
+  - send_line: set -o 2>&1 | wc -l
349
+  expect_output: '[0-9]+'
350
+  match_type: regex
351
+- name: '103. SHIFT EDGE CASES: shift with count'
352
+  steps:
353
+  - send_line: set -- a b c d e; shift 3; echo $1
354
+  expect_output: 'd'
355
+  match_type: contains
356
+- name: '103. SHIFT EDGE CASES: shift too many (exit code)'
357
+  steps:
358
+  - send_line: set -- a b; shift 5 2>/dev/null
359
+  - send_line: echo "EXIT=$?"
360
+  expect_output: EXIT=1
361
+  match_type: contains
362
+- name: '103. SHIFT EDGE CASES: shift zero'
363
+  steps:
364
+  - send_line: set -- a b c; shift 0; echo $#
365
+  expect_output: '3'
366
+  match_type: contains
367
+- name: '103. SHIFT EDGE CASES: shift all'
368
+  steps:
369
+  - send_line: set -- a b c; shift 3; echo $#
370
+  expect_output: '0'
371
+  match_type: contains
372
+- name: '103. SHIFT EDGE CASES: shift with no args (exit code)'
373
+  steps:
374
+  - send_line: set --; shift 2>/dev/null
375
+  - send_line: echo "EXIT=$?"
376
+  expect_output: EXIT=1
377
+  match_type: contains
378
+- name: '104. EVAL EDGE CASES: eval with semicolons'
379
+  steps:
380
+  - send_line: eval 'echo a; echo b' | wc -l
381
+  expect_output: '2'
382
+  match_type: contains
383
+- name: '104. EVAL EDGE CASES: eval with pipes'
384
+  steps:
385
+  - send_line: eval 'echo test | cat'
386
+  expect_output: test
387
+  match_type: contains
388
+  auto_fixed: shell_execution
389
+- name: '104. EVAL EDGE CASES: eval with redirects'
390
+  steps:
391
+  - send_line: eval 'echo test > /tmp/posix_gaps_eval_$$'; cat /tmp/posix_gaps_eval_$$;
392
+      rm -f /tmp/posix_gaps_eval_$$
393
+  expect_output: test
394
+  match_type: contains
395
+  auto_fixed: shell_execution
396
+- name: '104. EVAL EDGE CASES: eval double expansion'
397
+  steps:
398
+  - send_line: VAR='echo $HOME'; eval $VAR | grep -c /
399
+  expect_output: '[0-9]+'
400
+  match_type: regex
401
+- name: '104. EVAL EDGE CASES: eval empty string'
402
+  steps:
403
+  - send_line: eval ''; echo ok
404
+  expect_output: ok
405
+  match_type: contains
406
+- name: '104. EVAL EDGE CASES: nested eval'
407
+  steps:
408
+  - send_line: eval eval echo nested
409
+  expect_output: nested
410
+  match_type: contains
411
+  auto_fixed: shell_execution
412
+- name: '105. READONLY AND UNSET INTERACTIONS: readonly then unset fails (exit code)'
413
+  steps:
414
+  - send_line: readonly X=1; unset X 2>/dev/null
415
+  - send_line: echo "EXIT=$?"
416
+  expect_output: EXIT=1
417
+  match_type: contains
418
+- name: '105. READONLY AND UNSET INTERACTIONS: export readonly (exit code)'
419
+  steps:
420
+  - send_line: readonly XP=1; export XP; sh -c 'echo $XP' | grep -c 1
421
+  - send_line: echo "EXIT=$?"
422
+  expect_output: EXIT=0
423
+  match_type: contains
424
+- name: '105. READONLY AND UNSET INTERACTIONS: readonly in subshell'
425
+  steps:
426
+  - send_line: (readonly Y=2; echo $Y); readonly | grep -c Y || echo 0
427
+  expect_output: '[0-9]+'
428
+  match_type: regex
429
+- name: '106. RETURN BUILTIN EDGE CASES: return without function'
430
+  steps:
431
+  - send_line: return 2>/dev/null || echo ok
432
+  expect_output: ok
433
+  match_type: contains
434
+  auto_fixed: shell_execution
435
+- name: '106. RETURN BUILTIN EDGE CASES: return value preserved'
436
+  steps:
437
+  - send_line: f() { return 42; }; f; echo $?
438
+  expect_output: '42'
439
+  match_type: contains
440
+- name: '106. RETURN BUILTIN EDGE CASES: return in sourced script'
441
+  steps:
442
+  - send_line: echo 'return 7' > /tmp/posix_gaps_source_$$; . /tmp/posix_gaps_source_$$
443
+      2>/dev/null || echo $?; rm -f /tmp/posix_gaps_source_$$
444
+  expect_output: '7'
445
+  match_type: contains
446
+- name: '107. DOT (.) BUILTIN EDGE CASES: source with PATH search'
447
+  steps:
448
+  - send_line: echo 'echo sourced' > /tmp/posix_gaps_dot_$$; PATH=/tmp:$PATH; . posix_gaps_dot_$$
449
+      2>/dev/null || echo 'not found'; rm -f /tmp/posix_gaps_dot_$$
450
+  expect_output: sourced
451
+  match_type: contains
452
+  auto_fixed: shell_execution
453
+- name: '107. DOT (.) BUILTIN EDGE CASES: source nonexistent (exit code)'
454
+  steps:
455
+  - send_line: . /tmp/posix_gaps_nonexistent_$$ 2>/dev/null
456
+  - send_line: echo "EXIT=$?"
457
+  expect_output: EXIT=1
458
+  match_type: contains
459
+- name: '107. DOT (.) BUILTIN EDGE CASES: source preserves variables'
460
+  steps:
461
+  - send_line: echo 'A=from_source' > /tmp/posix_gaps_dot2_$$; . /tmp/posix_gaps_dot2_$$;
462
+      echo $A; rm -f /tmp/posix_gaps_dot2_$$
463
+  expect_output: from_source
464
+  match_type: contains
465
+- name: '108. BREAK AND CONTINUE EDGE CASES: break with level 0'
466
+  steps:
467
+  - send_line: for i in 1 2; do break 0 2>/dev/null || break; echo $i; done || echo
468
+      ok
469
+  expect_output: ok
470
+  match_type: contains
471
+  auto_fixed: shell_execution
472
+- name: '108. BREAK AND CONTINUE EDGE CASES: break level too high'
473
+  steps:
474
+  - send_line: for i in 1 2; do break 10 2>/dev/null || break; echo $i; done || echo
475
+      done
476
+  expect_output: ''
477
+  match_type: exact
478
+- name: '108. BREAK AND CONTINUE EDGE CASES: continue with level'
479
+  steps:
480
+  - send_line: for i in 1 2; do for j in a b; do continue 2 2>/dev/null || continue;
481
+      echo $i$j; done; done || echo ok
482
+  expect_output: ''
483
+  match_type: exact
484
+- name: '108. BREAK AND CONTINUE EDGE CASES: break outside loop'
485
+  steps:
486
+  - send_line: break 2>/dev/null || echo ok
487
+  expect_output: ok
488
+  match_type: contains
489
+  auto_fixed: manual_determination
490
+- name: '108. BREAK AND CONTINUE EDGE CASES: continue outside loop'
491
+  steps:
492
+  - send_line: continue 2>/dev/null || echo ok
493
+  expect_output: ok
494
+  match_type: contains
495
+  auto_fixed: manual_determination
496
+- name: '109. CASE STATEMENT EDGE CASES: case empty pattern'
497
+  steps:
498
+  - send_line: x=''; case $x in '') echo empty;; esac
499
+  expect_output: empty
500
+  match_type: contains
501
+  auto_fixed: shell_execution
502
+- name: '109. CASE STATEMENT EDGE CASES: case no match'
503
+  steps:
504
+  - send_line: x=z; case $x in a) echo a;; b) echo b;; esac; echo ok
505
+  expect_output: ok
506
+  match_type: contains
507
+- name: '109. CASE STATEMENT EDGE CASES: case with quotes'
508
+  steps:
509
+  - send_line: x='a b'; case $x in 'a b') echo match;; esac
510
+  expect_output: match
511
+  match_type: contains
512
+  auto_fixed: shell_execution
513
+- name: '109. CASE STATEMENT EDGE CASES: case glob vs literal'
514
+  steps:
515
+  - send_line: x='*'; case $x in '*') echo literal;; esac
516
+  expect_output: literal
517
+  match_type: contains
518
+  auto_fixed: shell_execution
519
+- name: '109. CASE STATEMENT EDGE CASES: case bracket range'
520
+  steps:
521
+  - send_line: x=b; case $x in [a-c]) echo range;; esac
522
+  expect_output: range
523
+  match_type: contains
524
+  auto_fixed: shell_execution
525
+- name: '109. CASE STATEMENT EDGE CASES: case multiple patterns order'
526
+  steps:
527
+  - send_line: x=a; case $x in a|b) echo first;; a) echo second;; esac
528
+  expect_output: first
529
+  match_type: contains
530
+  auto_fixed: shell_execution
531
+- name: '109. CASE STATEMENT EDGE CASES: case with variable pattern'
532
+  steps:
533
+  - send_line: P='a*'; x=abc; case $x in $P) echo var_pattern;; esac
534
+  expect_output: var_pattern
535
+  match_type: contains
536
+  auto_fixed: shell_execution
537
+- name: '110. FOR LOOP EDGE CASES: for empty word list'
538
+  steps:
539
+  - send_line: for i in; do echo $i; done; echo empty
540
+  expect_output: empty
541
+  match_type: contains
542
+- name: '110. FOR LOOP EDGE CASES: for single item'
543
+  steps:
544
+  - send_line: for i in one; do echo $i; done
545
+  expect_output: one
546
+  match_type: contains
547
+- name: '110. FOR LOOP EDGE CASES: for with glob expansion'
548
+  steps:
549
+  - send_line: touch /tmp/posix_gaps_for{1,2,3}_$$.txt 2>/dev/null; for f in /tmp/posix_gaps_for*_$$.txt;
550
+      do test -f $f && echo yes; done | head -1; rm -f /tmp/posix_gaps_for*_$$.txt
551
+  expect_output: 'yes'
552
+  match_type: contains
553
+  auto_fixed: shell_execution
554
+- name: '110. FOR LOOP EDGE CASES: for preserves IFS'
555
+  steps:
556
+  - send_line: IFS=:; for i in a b c; do echo $i; done; echo $IFS | od -A n -t x1
557
+      | grep -c 3a
558
+  expect_output: '1'
559
+  match_type: contains
560
+  auto_fixed: manual_determination
561
+- name: '111. WHILE AND UNTIL EDGE CASES: while true with break'
562
+  steps:
563
+  - send_line: i=0; while true; do i=$((i+1)); test $i -eq 3 && break; done; echo
564
+      $i
565
+  expect_output: '3'
566
+  match_type: contains
567
+  auto_fixed: shell_execution
568
+- name: '111. WHILE AND UNTIL EDGE CASES: until false with break'
569
+  steps:
570
+  - send_line: i=0; until false; do i=$((i+1)); test $i -eq 3 && break; done; echo
571
+      $i
572
+  expect_output: '3'
573
+  match_type: contains
574
+  auto_fixed: shell_execution
575
+- name: '111. WHILE AND UNTIL EDGE CASES: while with exit status'
576
+  steps:
577
+  - send_line: i=5; while [ $i -gt 0 ]; do i=$((i-1)); done; echo $?
578
+  expect_output: '0'
579
+  match_type: contains
580
+  auto_fixed: shell_execution
581
+- name: '111. WHILE AND UNTIL EDGE CASES: until with complex condition'
582
+  steps:
583
+  - send_line: i=0; until [ $i -gt 3 ] && [ $i -lt 10 ]; do i=$((i+1)); done; echo
584
+      $i
585
+  expect_output: '4'
586
+  match_type: contains
587
+  auto_fixed: shell_execution
588
+- name: '112. SUBSHELL VARIABLE ISOLATION: subshell doesnt modify parent'
589
+  steps:
590
+  - send_line: (X=inner); echo ${X:-unset}
591
+  expect_output: unset
592
+  match_type: contains
593
+- name: '112. SUBSHELL VARIABLE ISOLATION: subshell inherits variables'
594
+  steps:
595
+  - send_line: X=outer; (echo $X)
596
+  expect_output: outer
597
+  match_type: contains
598
+- name: '112. SUBSHELL VARIABLE ISOLATION: nested subshells'
599
+  steps:
600
+  - send_line: X=1; (X=2; (X=3; echo $X); echo $X); echo $X
601
+  expect_output: '3'
602
+  match_type: contains
603
+- name: '112. SUBSHELL VARIABLE ISOLATION: subshell with exports'
604
+  steps:
605
+  - send_line: export X=exp; (X=inner; echo $X); echo $X
606
+  expect_output: inner
607
+  match_type: contains
608
+- name: '113. BRACE GROUP SCOPING: brace group modifies parent'
609
+  steps:
610
+  - send_line: X=1; { X=2; }; echo $X
611
+  expect_output: '2'
612
+  match_type: contains
613
+- name: '113. BRACE GROUP SCOPING: brace group with redirects'
614
+  steps:
615
+  - send_line: '{ echo a; echo b; } | wc -l'
616
+  expect_output: '[0-9]+'
617
+  match_type: regex
618
+- name: '113. BRACE GROUP SCOPING: nested brace groups'
619
+  steps:
620
+  - send_line: X=1; { { X=2; }; echo $X; }; echo $X
621
+  expect_output: '2'
622
+  match_type: contains
623
+- name: '114. ALIAS EDGE CASES: alias with args'
624
+  steps:
625
+  - send_line: alias ll='ls -l'; alias ll | grep -c 'ls -l'
626
+  expect_output: '[0-9]+'
627
+  match_type: regex
628
+- name: '114. ALIAS EDGE CASES: alias recursive prevention'
629
+  steps:
630
+  - send_line: alias ls='ls -a'; command ls /tmp >/dev/null; echo $?
631
+  expect_output: '0'
632
+  match_type: contains
633
+- name: '114. ALIAS EDGE CASES: unalias nonexistent'
634
+  steps:
635
+  - send_line: unalias nonexistent_alias_$$ 2>/dev/null || echo ok
636
+  expect_output: ok
637
+  match_type: contains
638
+  auto_fixed: shell_execution
639
+- name: '114. ALIAS EDGE CASES: alias name same as builtin'
640
+  steps:
641
+  - send_line: alias echo='printf'; unalias echo; command -v echo | grep -c echo
642
+  expect_output: '[0-9]+'
643
+  match_type: regex
644
+- name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test complex AND/OR (exit code)'
645
+  steps:
646
+  - send_line: test 5 -gt 3 -a \( 10 -lt 20 -o 1 -eq 2 \)
647
+  - send_line: echo "EXIT=$?"
648
+  expect_output: EXIT=0
649
+  match_type: contains
650
+- name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test negation precedence (exit code)'
651
+  steps:
652
+  - send_line: test ! 5 -gt 10
653
+  - send_line: echo "EXIT=$?"
654
+  expect_output: EXIT=0
655
+  match_type: contains
656
+- name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string empty (exit code)'
657
+  steps:
658
+  - send_line: test -z ''
659
+  - send_line: echo "EXIT=$?"
660
+  expect_output: EXIT=0
661
+  match_type: contains
662
+- name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string nonempty (exit code)'
663
+  steps:
664
+  - send_line: test -n 'x'
665
+  - send_line: echo "EXIT=$?"
666
+  expect_output: EXIT=0
667
+  match_type: contains
668
+- name: '115. TEST COMMAND COMPLEX EXPRESSIONS: test string unary (exit code)'
669
+  steps:
670
+  - send_line: test 'nonempty'
671
+  - send_line: echo "EXIT=$?"
672
+  expect_output: EXIT=0
673
+  match_type: contains
674
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$@ with IFS'
675
+  steps:
676
+  - send_line: 'IFS=:; set -- a b c; echo "$@"'
677
+  expect_output: 'a b c'
678
+  match_type: contains
679
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$* vs \$@ unquoted'
680
+  steps:
681
+  - send_line: set -- a b c; for x in $*; do echo $x; done | wc -l
682
+  expect_output: '[0-9]+'
683
+  match_type: regex
684
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$@ quoted iteration'
685
+  steps:
686
+  - send_line: 'set -- "a b" "c d"; for x in "$@"; do echo "$x"; done | wc -l'
687
+  expect_output: '2'
688
+  match_type: contains
689
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$# after shift'
690
+  steps:
691
+  - send_line: set -- a b c; shift; echo $#
692
+  expect_output: '2'
693
+  match_type: contains
694
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$- shows options'
695
+  steps:
696
+  - send_line: echo $- | grep -c '[a-z]'
697
+  expect_output: '1'
698
+  match_type: contains
699
+  auto_fixed: shell_execution
700
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$\$ is numeric'
701
+  steps:
702
+  - send_line: echo $$ | grep -c '^[0-9]*$'
703
+  expect_output: '1'
704
+  match_type: contains
705
+  auto_fixed: shell_execution
706
+- name: '116. SPECIAL PARAMETER EDGE CASES: \$! after background'
707
+  steps:
708
+  - send_line: sleep 0.1 & echo $! | grep -c '^[0-9]*$'
709
+  expect_output: '[0-9]+'
710
+  match_type: regex
711
+- name: '117. TILDE EXPANSION EDGE CASES: tilde in assignment'
712
+  steps:
713
+  - send_line: VAR=~/test; echo $VAR | grep -c '^/'
714
+  expect_output: '1'
715
+  match_type: contains
716
+- name: '117. TILDE EXPANSION EDGE CASES: tilde in middle no expand'
717
+  steps:
718
+  - send_line: echo a~b | grep -c '~'
719
+  expect_output: '1'
720
+  match_type: contains
721
+- name: '117. TILDE EXPANSION EDGE CASES: tilde in quotes no expand'
722
+  steps:
723
+  - send_line: echo '~' | grep -c '~'
724
+  expect_output: '1'
725
+  match_type: contains
726
+- name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst nested'
727
+  steps:
728
+  - send_line: echo $(echo $(echo nested))
729
+  expect_output: nested
730
+  match_type: contains
731
+  auto_fixed: shell_execution
732
+- name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst with pipes'
733
+  steps:
734
+  - send_line: echo $(echo a | cat)
735
+  expect_output: a
736
+  match_type: contains
737
+  auto_fixed: shell_execution
738
+- name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst multiline'
739
+  steps:
740
+  - send_line: 'result=$(echo a; echo b); echo "$result"'
741
+  expect_output: 'a'
742
+  match_type: contains
743
+- name: '118. COMMAND SUBSTITUTION EDGE CASES: command subst empty'
744
+  steps:
745
+  - send_line: 'x=$(true); echo "len=${#x}"'
746
+  expect_output: 'len=0'
747
+  match_type: contains
748
+- name: '118. COMMAND SUBSTITUTION EDGE CASES: backtick vs dollar-paren'
749
+  steps:
750
+  - send_line: 'a=`echo test`; b=$(echo test); test "$a" = "$b" && echo same'
751
+  expect_output: 'same'
752
+  match_type: contains
753
+- name: '119. REDIRECT EDGE CASES: redirect order matters'
754
+  steps:
755
+  - send_line: echo test 2>&1 >/dev/null | wc -l
756
+  expect_output: '0'
757
+  match_type: contains
758
+- name: '119. REDIRECT EDGE CASES: redirect to same fd'
759
+  steps:
760
+  - send_line: echo test >&1 2>&1
761
+  expect_output: test
762
+  match_type: contains
763
+- name: '119. REDIRECT EDGE CASES: redirect append'
764
+  steps:
765
+  - send_line: echo a > /tmp/posix_gaps_redir_$$; echo b >> /tmp/posix_gaps_redir_$$;
766
+      wc -l < /tmp/posix_gaps_redir_$$; rm -f /tmp/posix_gaps_redir_$$
767
+  expect_output: '2'
768
+  match_type: contains
769
+  auto_fixed: shell_execution
770
+- name: '120. WAIT BUILTIN EDGE CASES: wait for background job (exit code)'
771
+  steps:
772
+  - send_line: '(sleep 0.01 & pid=$!; wait $pid; echo EXIT=$?)'
773
+  expect_output: EXIT=0
774
+  match_type: contains
775
+- name: '120. WAIT BUILTIN EDGE CASES: wait all jobs (exit code)'
776
+  steps:
777
+  - send_line: '(sleep 0.01 & sleep 0.01 & wait; echo EXIT=$?)'
778
+  expect_output: EXIT=0
779
+  match_type: contains
780
+- name: '120. WAIT BUILTIN EDGE CASES: wait nonexistent PID (exit code)'
781
+  steps:
782
+  - send_line: wait 9999999 2>/dev/null
783
+  - send_line: echo "EXIT=$?"
784
+  expect_output: EXIT=127
785
+  match_type: contains
786
+- name: '120. WAIT BUILTIN EDGE CASES: wait preserves exit status'
787
+  steps:
788
+  - send_line: sh -c 'exit 42' & pid=$!; wait $pid; echo $?
789
+  expect_output: '42'
790
+  match_type: contains
791
+- name: '121. GETOPTS COMPREHENSIVE: getopts basic'
792
+  steps:
793
+  - send_line: set -- -a test; getopts 'a:' opt; echo $opt
794
+  expect_output: 'a'
795
+  match_type: contains
796
+- name: '121. GETOPTS COMPREHENSIVE: getopts OPTARG'
797
+  steps:
798
+  - send_line: set -- -a value; getopts 'a:' opt; echo $OPTARG
799
+  expect_output: 'value'
800
+  match_type: contains
801
+- name: '121. GETOPTS COMPREHENSIVE: getopts OPTIND'
802
+  steps:
803
+  - send_line: set -- -a -b; getopts 'ab' opt; echo $OPTIND
804
+  expect_output: '2'
805
+  match_type: contains
806
+- name: '121. GETOPTS COMPREHENSIVE: getopts invalid option'
807
+  steps:
808
+  - send_line: set -- -z; getopts 'ab' opt 2>/dev/null; echo $opt | grep -c '?'
809
+  expect_output: '1'
810
+  match_type: contains
811
+  auto_fixed: shell_execution
812
+- name: '122. UMASK EDGE CASES: umask get'
813
+  steps:
814
+  - send_line: umask | grep -c '^[0-9]*$'
815
+  expect_output: '[0-9]+'
816
+  match_type: regex
817
+- name: '122. UMASK EDGE CASES: umask set and get'
818
+  steps:
819
+  - send_line: old=$(umask); umask 022; umask; umask $old | head -1
820
+  expect_output: '0022'
821
+  match_type: contains
822
+  auto_fixed: shell_execution
823
+- name: '123. HASH BUILTIN EDGE CASES: hash command (exit code)'
824
+  steps:
825
+  - send_line: hash echo 2>/dev/null
826
+  - send_line: echo "EXIT=$?"
827
+  expect_output: EXIT=0
828
+  match_type: contains
829
+- name: '123. HASH BUILTIN EDGE CASES: hash -r clears (exit code)'
830
+  steps:
831
+  - send_line: hash -r
832
+  - send_line: echo "EXIT=$?"
833
+  expect_output: EXIT=0
834
+  match_type: contains
835
+- name: '123. HASH BUILTIN EDGE CASES: hash nonexistent'
836
+  steps:
837
+  - send_line: hash nonexistent_cmd_$$ 2>&1 | grep -c 'not found\\|hash'
838
+  expect_output: '[0-9]+'
839
+  match_type: regex
840
+- name: '124. TYPE BUILTIN EDGE CASES: type builtin'
841
+  steps:
842
+  - send_line: type echo | grep -ci 'builtin\\|built-in\\|shell builtin'
843
+  expect_output: '[0-9]+'
844
+  match_type: regex
845
+- name: '124. TYPE BUILTIN EDGE CASES: type function'
846
+  steps:
847
+  - send_line: f() { :; }; type f | grep -c function
848
+  expect_output: '[0-9]+'
849
+  match_type: regex
850
+- name: '124. TYPE BUILTIN EDGE CASES: type external'
851
+  steps:
852
+  - send_line: type cat | grep -c '/'
853
+  expect_output: '[0-9]+'
854
+  match_type: regex
855
+- name: '124. TYPE BUILTIN EDGE CASES: type nonexistent (exit code)'
856
+  steps:
857
+  - send_line: type nonexistent_$$ 2>/dev/null
858
+  - send_line: echo "EXIT=$?"
859
+  expect_output: EXIT=1
860
+  match_type: contains
861
+- name: '125. TIMES BUILTIN: times output format'
862
+  steps:
863
+  - send_line: times | wc -l
864
+  expect_output: '[0-9]+'
865
+  match_type: regex
866
+- name: '125. TIMES BUILTIN: times exit status (exit code)'
867
+  steps:
868
+  - send_line: times >/dev/null
869
+  - send_line: echo "EXIT=$?"
870
+  expect_output: EXIT=0
871
+  match_type: contains
872
+- name: '126. TRAP SIGNAL EDGE CASES: trap with signal number'
873
+  steps:
874
+  - send_line: trap 'echo sig' 15; trap | grep -c 15
875
+  expect_output: '[0-9]+'
876
+  match_type: regex
877
+- name: '126. TRAP SIGNAL EDGE CASES: trap with multiple signals'
878
+  steps:
879
+  - send_line: trap 'echo multi' INT TERM; trap | grep -c 'echo multi'
880
+  expect_output: '[0-9]+'
881
+  match_type: regex
882
+- name: '126. TRAP SIGNAL EDGE CASES: trap ignore signal'
883
+  steps:
884
+  - send_line: trap '' INT; trap | grep INT | grep -c ''
885
+  expect_output: '[0-9]+'
886
+  match_type: regex
887
+- name: '127. EMPTY AND WHITESPACE EDGE CASES: empty command in list'
888
+  steps:
889
+  - send_line: ': ; echo ok'
890
+  expect_output: ok
891
+  match_type: contains
892
+- name: '127. EMPTY AND WHITESPACE EDGE CASES: whitespace only'
893
+  steps:
894
+  - send_line: '   ; echo ok'
895
+  expect_output: ok
896
+  match_type: contains
897
+- name: '127. EMPTY AND WHITESPACE EDGE CASES: multiple empty commands'
898
+  steps:
899
+  - send_line: ': ; : ; echo ok'
900
+  expect_output: ok
901
+  match_type: contains
902
+- name: '127. EMPTY AND WHITESPACE EDGE CASES: empty string as command'
903
+  steps:
904
+  - send_line: ''''' 2>/dev/null || echo ok'
905
+  expect_output: ok
906
+  match_type: contains
907
+  auto_fixed: shell_execution
908
+- name: '128. COMPLEX PIPELINES: five stage pipeline'
909
+  steps:
910
+  - send_line: echo test | cat | cat | cat | cat
911
+  expect_output: test
912
+  match_type: contains
913
+- name: '128. COMPLEX PIPELINES: pipeline with negation (exit code)'
914
+  steps:
915
+  - send_line: '! false | false'
916
+  - send_line: echo "EXIT=$?"
917
+  expect_output: EXIT=0
918
+  match_type: contains
919
+- name: '128. COMPLEX PIPELINES: pipeline with subshell'
920
+  steps:
921
+  - send_line: (echo a; echo b) | wc -l
922
+  expect_output: '2'
923
+  match_type: contains
924
+- name: '128. COMPLEX PIPELINES: pipeline with brace group'
925
+  steps:
926
+  - send_line: '{ echo x; echo y; } | wc -l'
927
+  expect_output: '[0-9]+'
928
+  match_type: regex
929
+- name: '129. EXIT BUILTIN EDGE CASES: exit with status (exit code)'
930
+  steps:
931
+  - send_line: sh -c 'exit 42'
932
+  - send_line: echo "EXIT=$?"
933
+  expect_output: EXIT=42
934
+  match_type: contains
935
+- name: '129. EXIT BUILTIN EDGE CASES: exit in subshell (exit code)'
936
+  steps:
937
+  - send_line: (exit 7); echo $?
938
+  - send_line: echo "EXIT=$?"
939
+  expect_output: EXIT=0
940
+  match_type: contains
941
+- name: '130. EXPORT EDGE CASES: export without value'
942
+  steps:
943
+  - send_line: export VAR; sh -c 'echo ${VAR:-unset}'
944
+  expect_output: unset
945
+  match_type: contains
946
+- name: '130. EXPORT EDGE CASES: export with value'
947
+  steps:
948
+  - send_line: export VAR=value; sh -c 'echo $VAR'
949
+  expect_output: value
950
+  match_type: contains
951
+- name: '130. EXPORT EDGE CASES: export multiple'
952
+  steps:
953
+  - send_line: export A=1 B=2; sh -c 'echo $A $B'
954
+  expect_output: 1 2
955
+  match_type: contains
956
+- name: '130. EXPORT EDGE CASES: export readonly'
957
+  steps:
958
+  - send_line: readonly XR=ro; export XR; sh -c 'echo $XR'
959
+  expect_output: ro
960
+  match_type: contains
suites/interactive/posix/posix_untested_auto.yamladded
@@ -0,0 +1,195 @@
1
+metadata:
2
+  category: Untested
3
+  description: Tests converted from POSIX compliance suite
4
+  auto_generated: true
5
+  needs_review: Tests with MANUAL_REVIEW need expected output verification
6
+tests:
7
+- name: '131. COMMAND BUILTIN - PATH SEARCH: command -v ls'
8
+  steps:
9
+  - send_line: command -v ls >/dev/null && echo found
10
+  expect_output: found
11
+  match_type: contains
12
+  auto_fixed: shell_execution
13
+- name: '131. COMMAND BUILTIN - PATH SEARCH: command -v nonexistent'
14
+  steps:
15
+  - send_line: command -v nonexistent >/dev/null || echo notfound
16
+  expect_output: notfound
17
+  match_type: contains
18
+  auto_fixed: shell_execution
19
+- name: '131. COMMAND BUILTIN - PATH SEARCH: command without options'
20
+  steps:
21
+  - send_line: command echo test
22
+  expect_output: test
23
+  match_type: contains
24
+  auto_fixed: shell_execution
25
+- name: '132. MULTI-FD REDIRECTIONS: fd 3 redirect write'
26
+  steps:
27
+  - send_line: exec 3>/tmp/posix_fd3.txt; echo test >&3; exec 3>&-; cat /tmp/posix_fd3.txt;
28
+      rm /tmp/posix_fd3.txt
29
+  expect_output: test
30
+  match_type: contains
31
+  auto_fixed: shell_execution
32
+- name: '132. MULTI-FD REDIRECTIONS: fd 4 redirect read'
33
+  steps:
34
+  - send_line: echo data > /tmp/posix_fd4.txt; exec 4</tmp/posix_fd4.txt; read line
35
+      <&4; echo $line; exec 4<&-; rm /tmp/posix_fd4.txt
36
+  expect_output: data
37
+  match_type: contains
38
+  auto_fixed: shell_execution
39
+- name: '132. MULTI-FD REDIRECTIONS: fd duplication'
40
+  steps:
41
+  - send_line: exec 5>&1; echo stdout >&5; exec 5>&-
42
+  expect_output: stdout
43
+  match_type: contains
44
+  auto_fixed: shell_execution
45
+- name: '132. MULTI-FD REDIRECTIONS: fd 3 and 4 together'
46
+  steps:
47
+  - send_line: exec 3>/tmp/posix_3.txt 4>/tmp/posix_4.txt; echo a >&3; echo b >&4;
48
+      exec 3>&- 4>&-; cat /tmp/posix_3.txt /tmp/posix_4.txt; rm /tmp/posix_3.txt /tmp/posix_4.txt
49
+  expect_output: 'a'
50
+  match_type: contains
51
+- name: '133. EXEC WITH SHELL REDIRECTIONS: exec redirect stdout'
52
+  steps:
53
+  - send_line: exec 3>&1; exec >/tmp/posix_exec_out.txt; echo redirected; exec >&3;
54
+      cat /tmp/posix_exec_out.txt; rm /tmp/posix_exec_out.txt
55
+  expect_output: redirected
56
+  match_type: contains
57
+  auto_fixed: shell_execution
58
+- name: '133. EXEC WITH SHELL REDIRECTIONS: exec redirect stdin'
59
+  steps:
60
+  - send_line: echo testdata > /tmp/posix_exec_in.txt; exec </tmp/posix_exec_in.txt;
61
+      read data; echo $data; rm /tmp/posix_exec_in.txt
62
+  expect_output: testdata
63
+  match_type: contains
64
+  auto_fixed: shell_execution
65
+- name: '134. SET OPTION INTERACTIONS: set -e with true'
66
+  steps:
67
+  - send_line: set -e; true; echo ok
68
+  expect_output: ok
69
+  match_type: contains
70
+- name: '134. SET OPTION INTERACTIONS: set -u with unset var'
71
+  steps:
72
+  - send_line: set -u; echo ${UNSET_VAR:-default}
73
+  expect_output: default
74
+  match_type: contains
75
+  auto_fixed: shell_execution
76
+- name: '134. SET OPTION INTERACTIONS: set -C noclobber'
77
+  steps:
78
+  - send_line: set -C; echo test > /tmp/posix_clobber.txt; echo ok; rm /tmp/posix_clobber.txt
79
+  expect_output: ok
80
+  match_type: contains
81
+  auto_fixed: shell_execution
82
+- name: '134. SET OPTION INTERACTIONS: set -C override with >|'
83
+  steps:
84
+  - send_line: set -C; echo test > /tmp/posix_clobber2.txt; echo override >| /tmp/posix_clobber2.txt;
85
+      cat /tmp/posix_clobber2.txt; rm /tmp/posix_clobber2.txt
86
+  expect_output: override
87
+  match_type: contains
88
+  auto_fixed: shell_execution
89
+- name: '135. SPECIAL BUILTIN ERROR HANDLING: readonly error exits'
90
+  steps:
91
+  - send_line: (readonly VAR=1; VAR=2 2>/dev/null; echo should not print) || echo
92
+      exited
93
+  expect_output: exited
94
+  match_type: contains
95
+- name: '135. SPECIAL BUILTIN ERROR HANDLING: export invalid'
96
+  steps:
97
+  - send_line: (export 123INVALID=value 2>/dev/null; echo should not print) || echo
98
+      exited
99
+  expect_output: should not print
100
+  match_type: contains
101
+- name: '135. SPECIAL BUILTIN ERROR HANDLING: set invalid option'
102
+  steps:
103
+  - send_line: (set -@ 2>/dev/null; echo should not print) || echo exited
104
+  expect_output: exited
105
+  match_type: contains
106
+- name: '137. NESTED PARAMETER EXPANSION: nested default'
107
+  steps:
108
+  - send_line: unset A B; echo ${A:-${B:-default}}
109
+  expect_output: default
110
+  match_type: contains
111
+  auto_fixed: shell_execution
112
+- name: '137. NESTED PARAMETER EXPANSION: nested with set var'
113
+  steps:
114
+  - send_line: A=inner; unset B; echo ${B:-${A}}
115
+  expect_output: inner
116
+  match_type: contains
117
+  auto_fixed: shell_execution
118
+- name: '137. NESTED PARAMETER EXPANSION: double nested'
119
+  steps:
120
+  - send_line: unset A B C; echo ${A:-${B:-${C:-triple}}}
121
+  expect_output: triple
122
+  match_type: contains
123
+  auto_fixed: shell_execution
124
+- name: '138. PARAMETER LENGTH EDGE CASES: length of $@'
125
+  steps:
126
+  - send_line: set -- a b c; echo ${#@}
127
+  expect_output: '3'
128
+  match_type: contains
129
+  auto_fixed: shell_execution
130
+- name: '138. PARAMETER LENGTH EDGE CASES: length of $*'
131
+  steps:
132
+  - send_line: set -- a b c; echo ${#*}
133
+  expect_output: '3'
134
+  match_type: contains
135
+  auto_fixed: shell_execution
136
+- name: '138. PARAMETER LENGTH EDGE CASES: length of empty'
137
+  steps:
138
+  - send_line: VAR=; echo ${#VAR}
139
+  expect_output: '0'
140
+  match_type: contains
141
+  auto_fixed: shell_execution
142
+- name: '138. PARAMETER LENGTH EDGE CASES: length of unset'
143
+  steps:
144
+  - send_line: unset VAR; echo ${#VAR}
145
+  expect_output: '0'
146
+  match_type: contains
147
+  auto_fixed: shell_execution
148
+- name: '139. QUOTING EDGE CASES: empty double quotes'
149
+  steps:
150
+  - send_line: VAR=""; echo x${VAR}y
151
+  expect_output: xy
152
+  match_type: contains
153
+  auto_fixed: shell_execution
154
+- name: '139. QUOTING EDGE CASES: empty single quotes'
155
+  steps:
156
+  - send_line: VAR=''; echo x${VAR}y
157
+  expect_output: xy
158
+  match_type: contains
159
+- name: '139. QUOTING EDGE CASES: adjacent quotes concat'
160
+  steps:
161
+  - send_line: echo "a"b"c"
162
+  expect_output: a"b"c
163
+  match_type: contains
164
+- name: '139. QUOTING EDGE CASES: quote in quote'
165
+  steps:
166
+  - send_line: echo "it
167
+  expect_output: it
168
+  match_type: contains
169
+- name: '142. REDIRECTION EDGE CASES: close stdin'
170
+  steps:
171
+  - send_line: cat <&- 2>&1 | head -1 || echo ok
172
+  expect_output: ok
173
+  match_type: contains
174
+- name: '142. REDIRECTION EDGE CASES: close stdout'
175
+  steps:
176
+  - send_line: echo test >&- 2>&1
177
+  expect_output: test >&- 2>&1
178
+  match_type: contains
179
+- name: '142. REDIRECTION EDGE CASES: read/write mode'
180
+  steps:
181
+  - send_line: echo data > /tmp/posix_rw.txt; cat <> /tmp/posix_rw.txt; rm /tmp/posix_rw.txt
182
+  expect_output: data > /tmp/posix_rw.txt; cat <> /tmp/posix_rw.txt; rm /tmp/posix_rw.txt
183
+  match_type: contains
184
+- name: '144. SET -n (NOEXEC) TESTING: set -n parse only'
185
+  steps:
186
+  - send_line: set -n; echo "should not execute"; false
187
+  expect_output: ''
188
+  match_type: contains
189
+  auto_fixed: manual_determination
190
+- name: '145. SET -m (MONITOR) TESTING: set -m doesn''t affect output'
191
+  steps:
192
+  - send_line: set -m; echo test; set +m
193
+  expect_output: test
194
+  match_type: contains
195
+  auto_fixed: shell_execution
suites/interactive/posix/prompt_display.yamladded
@@ -0,0 +1,325 @@
1
+# Prompt and Display Tests for fortsh
2
+# Phase 6: Prompt customization, terminal display, window resize
3
+
4
+metadata:
5
+  category: "Prompt and Display"
6
+  description: "Tests for prompt customization and terminal display features"
7
+  phase: 6
8
+
9
+tests:
10
+  # =============================================================
11
+  # PS1 - PRIMARY PROMPT (verify prompt content appears)
12
+  # =============================================================
13
+  - name: "PS1 sets custom prompt"
14
+    steps:
15
+      - send_line: "PS1='CUSTOM> '"
16
+    expect_output: "CUSTOM>"
17
+    match_type: "contains"
18
+
19
+  - name: "PS1 with username escape shows username"
20
+    steps:
21
+      - send_line: "PS1='\\u$ '"
22
+    expect_output: "$"
23
+    match_type: "contains"
24
+
25
+  - name: "PS1 with hostname escape shows host"
26
+    steps:
27
+      - send_line: "PS1='\\h: '"
28
+    expect_output: ":"
29
+    match_type: "contains"
30
+
31
+  - name: "PS1 with working directory shows path"
32
+    steps:
33
+      - send_line: "PS1='W:\\w '"
34
+    expect_output: "W:"
35
+    match_type: "contains"
36
+
37
+  - name: "PS1 with short directory shows basename"
38
+    steps:
39
+      - send_line: "PS1='\\W> '"
40
+      - send_line: "cd /tmp"
41
+    expect_output: "tmp>"
42
+    match_type: "contains"
43
+
44
+  - name: "PS1 with time shows HH:MM:SS"
45
+    steps:
46
+      - send_line: "PS1='\\t '"
47
+    expect_output: ":"
48
+    match_type: "contains"
49
+
50
+  - name: "PS1 with date shows day"
51
+    steps:
52
+      - send_line: "PS1='\\d '"
53
+    expect_output: " "
54
+    match_type: "contains"
55
+
56
+  - name: "PS1 with shell name"
57
+    steps:
58
+      - send_line: "PS1='\\s> '"
59
+    expect_output: "fortsh>"
60
+    match_type: "contains"
61
+
62
+  - name: "PS1 with newline"
63
+    steps:
64
+      - send_line: "PS1='L1\\nL2> '"
65
+    expect_output: "L2>"
66
+    match_type: "contains"
67
+
68
+  - name: "PS1 with dollar sign for non-root"
69
+    steps:
70
+      - send_line: "PS1='D\\$ '"
71
+    expect_output: "D"
72
+    match_type: "contains"
73
+
74
+  - name: "PS1 with literal backslash"
75
+    steps:
76
+      - send_line: "PS1='\\\\> '"
77
+    expect_output: "\\>"
78
+    match_type: "contains"
79
+
80
+  - name: "PS1 with command substitution"
81
+    steps:
82
+      - send_line: "PS1='$(echo SUB)> '"
83
+    expect_output: "SUB>"
84
+    match_type: "contains"
85
+
86
+  - name: "PS1 updates after cd"
87
+    steps:
88
+      - send_line: "PS1='\\W> '"
89
+      - send_line: "cd /tmp"
90
+    expect_output: "tmp>"
91
+    match_type: "contains"
92
+
93
+  - name: "PS1 with variable expansion"
94
+    steps:
95
+      - send_line: "MYPS=TEST"
96
+      - send_line: "PS1='$MYPS> '"
97
+    expect_output: "TEST>"
98
+    match_type: "contains"
99
+
100
+  # =============================================================
101
+  # PS2 - CONTINUATION PROMPT
102
+  # =============================================================
103
+  - name: "PS2 shown for multiline for loop"
104
+    steps:
105
+      - send_line: "PS2='MORE> '"
106
+      - send: "for i in 1 2; do"
107
+      - send_key: "Enter"
108
+      - send: "echo $i"
109
+      - send_key: "Enter"
110
+      - send: "done"
111
+      - send_key: "Enter"
112
+    expect_output: "1"
113
+    match_type: "contains"
114
+
115
+  - name: "Incomplete quote shows continuation"
116
+    steps:
117
+      - send: "echo 'hello"
118
+      - send_key: "Enter"
119
+      - send: "world'"
120
+      - send_key: "Enter"
121
+    expect_output: "hello"
122
+    match_type: "contains"
123
+
124
+  - name: "Incomplete command with pipe"
125
+    steps:
126
+      - send: "echo test |"
127
+      - send_key: "Enter"
128
+      - send: "cat"
129
+      - send_key: "Enter"
130
+    expect_output: "test"
131
+    match_type: "contains"
132
+
133
+  # =============================================================
134
+  # PROMPT COLORS (test that prompts with escapes still work)
135
+  # =============================================================
136
+  - name: "PS1 with ANSI codes still displays"
137
+    steps:
138
+      - send_line: "PS1='\\033[31mRED\\033[0m> '"
139
+      - send_line: "echo COL987"
140
+    expect_output: "COL987"
141
+    match_type: "contains"
142
+
143
+  - name: "PS1 with multiple colors"
144
+    steps:
145
+      - send_line: "PS1='\\033[32mG\\033[0m> '"
146
+      - send_line: "echo MUL654"
147
+    expect_output: "MUL654"
148
+    match_type: "contains"
149
+
150
+  # =============================================================
151
+  # PROMPT EDGE CASES
152
+  # =============================================================
153
+  - name: "Empty PS1 still allows commands"
154
+    steps:
155
+      - send_line: "PS1=''; echo emptyps1"
156
+    expect_output: "emptyps1"
157
+    match_type: "contains"
158
+
159
+  - name: "Very long prompt"
160
+    steps:
161
+      - send_line: "PS1='LONGPROMPT> '"
162
+      - send_line: "echo XYZ123"
163
+    expect_output: "XYZ123"
164
+    match_type: "contains"
165
+
166
+  - name: "Special characters in prompt"
167
+    steps:
168
+      - send_line: "PS1='!@#> '"
169
+      - send_line: "echo ABC789"
170
+    expect_output: "ABC789"
171
+    match_type: "contains"
172
+
173
+  - name: "Unicode arrow in prompt"
174
+    steps:
175
+      - send_line: "PS1='→ '"
176
+      - send_line: "echo UNI456"
177
+    expect_output: "UNI456"
178
+    match_type: "contains"
179
+
180
+  - name: "Emoji in prompt"
181
+    steps:
182
+      - send_line: "PS1='🚀 '"
183
+      - send_line: "echo EMO321"
184
+    expect_output: "EMO321"
185
+    match_type: "contains"
186
+
187
+  # =============================================================
188
+  # WINDOW RESIZE (SIGWINCH)
189
+  # =============================================================
190
+  - name: "Handle terminal resize"
191
+    steps:
192
+      - resize:
193
+          rows: 40
194
+          cols: 120
195
+      - send_line: "echo resized"
196
+    expect_output: "resized"
197
+    match_type: "contains"
198
+
199
+  - name: "COLUMNS updated after resize"
200
+    steps:
201
+      - resize:
202
+          rows: 24
203
+          cols: 100
204
+      - send_line: "echo $COLUMNS"
205
+    expect_output: "100"
206
+    match_type: "contains"
207
+
208
+  - name: "LINES updated after resize"
209
+    steps:
210
+      - resize:
211
+          rows: 50
212
+          cols: 80
213
+      - send_line: "echo $LINES"
214
+    expect_output: "50"
215
+    match_type: "contains"
216
+
217
+  - name: "Prompt redraws after resize"
218
+    steps:
219
+      - send: "partial"
220
+      - resize:
221
+          rows: 30
222
+          cols: 100
223
+      - send_key: "C-u"
224
+      - send_line: "echo redraw"
225
+    expect_output: "redraw"
226
+    match_type: "contains"
227
+
228
+  - name: "Small terminal size"
229
+    steps:
230
+      - resize:
231
+          rows: 10
232
+          cols: 40
233
+      - send_line: "echo small"
234
+    expect_output: "small"
235
+    match_type: "contains"
236
+
237
+  - name: "Large terminal size"
238
+    steps:
239
+      - resize:
240
+          rows: 100
241
+          cols: 200
242
+      - send_line: "echo large"
243
+    expect_output: "large"
244
+    match_type: "contains"
245
+
246
+  # =============================================================
247
+  # LINE WRAPPING
248
+  # =============================================================
249
+  - name: "Long command wraps correctly"
250
+    steps:
251
+      - send_line: "echo this is a very long command that should wrap around the terminal edge properly"
252
+    expect_output: "wrap around"
253
+    match_type: "contains"
254
+
255
+  - name: "Editing wrapped line"
256
+    steps:
257
+      - send: "echo aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
258
+      - send_key: "C-a"
259
+      - send_key: "M-f"
260
+      - send_key: "C-k"
261
+      - send: " wrapped"
262
+      - send_key: "Enter"
263
+    expect_output: "wrapped"
264
+    match_type: "contains"
265
+
266
+  - name: "Cursor position on wrapped line"
267
+    steps:
268
+      - send: "echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
269
+      - send_key: "Home"
270
+      - send_key: "End"
271
+      - send_key: "C-u"
272
+      - send_line: "echo cursor"
273
+    expect_output: "cursor"
274
+    match_type: "contains"
275
+
276
+  # =============================================================
277
+  # CLEAR SCREEN
278
+  # =============================================================
279
+  - name: "Ctrl+L clears screen"
280
+    steps:
281
+      - send_line: "echo before"
282
+      - send_key: "C-l"
283
+      - send_line: "echo after"
284
+    expect_output: "after"
285
+    match_type: "contains"
286
+
287
+  - name: "clear command clears screen"
288
+    steps:
289
+      - send_line: "echo before"
290
+      - send_line: "clear"
291
+      - send_line: "echo after"
292
+    expect_output: "after"
293
+    match_type: "contains"
294
+
295
+  # =============================================================
296
+  # MULTILINE OUTPUT
297
+  # =============================================================
298
+  - name: "Multiple lines of output"
299
+    steps:
300
+      - send_line: "echo line1; echo line2; echo line3"
301
+    expect_output: "line2"
302
+    match_type: "contains"
303
+
304
+  - name: "Output with blank lines"
305
+    steps:
306
+      - send_line: "echo first; echo; echo last"
307
+    expect_output: "last"
308
+    match_type: "contains"
309
+
310
+  - name: "Long output scrolling"
311
+    steps:
312
+      - send_line: "for i in $(seq 1 20); do echo line$i; done"
313
+    expect_output: "line20"
314
+    match_type: "contains"
315
+
316
+  # =============================================================
317
+  # TERMINAL TITLE
318
+  # =============================================================
319
+  - name: "Set terminal title with printf"
320
+    steps:
321
+      - send_line: "printf '\\033]0;Test Title\\007'"
322
+      - send_line: "echo titleset"
323
+    expect_output: "titleset"
324
+    match_type: "contains"
325
+
suites/interactive/stress/stress.yamladded
@@ -0,0 +1,289 @@
1
+metadata:
2
+  category: Stress
3
+  description: Interactive stress tests for buffer limits, deep nesting, large values, and escape sequences
4
+tests:
5
+# ==========================================
6
+# 1. Long command lines
7
+# ==========================================
8
+- name: '1. LONG COMMANDS: 200-char echo'
9
+  steps:
10
+  - send_line: echo "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
11
+  expect_output: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
12
+  match_type: contains
13
+
14
+- name: '1. LONG COMMANDS: long pipeline'
15
+  steps:
16
+  - send_line: echo abcdefghij | cat | cat | cat | cat | cat | cat | cat | cat | cat | cat
17
+  expect_output: abcdefghij
18
+  match_type: contains
19
+
20
+- name: '1. LONG COMMANDS: long variable value'
21
+  steps:
22
+  - send_line: X=$(printf '%0200d' 0); echo ${#X}
23
+  expect_output: '200'
24
+  match_type: contains
25
+
26
+# ==========================================
27
+# 2. Escape sequences (the gap that triggered this)
28
+# ==========================================
29
+- name: '2. ESCAPE SEQUENCES: hex in dollar-single-quote'
30
+  steps:
31
+  - send_line: echo $'\x48\x65\x6c\x6c\x6f'
32
+  expect_output: Hello
33
+  match_type: contains
34
+
35
+- name: '2. ESCAPE SEQUENCES: octal in dollar-single-quote'
36
+  steps:
37
+  - send_line: echo $'\110\145\154\154\157'
38
+  expect_output: Hello
39
+  match_type: contains
40
+
41
+- name: '2. ESCAPE SEQUENCES: mixed escapes'
42
+  steps:
43
+  - send_line: echo $'\x41\t\x42\t\x43'
44
+  expect_output: A
45
+  match_type: contains
46
+
47
+- name: '2. ESCAPE SEQUENCES: tab in dollar-quote'
48
+  steps:
49
+  - send_line: echo $'a\tb'
50
+  expect_output: a
51
+  match_type: contains
52
+
53
+- name: '2. ESCAPE SEQUENCES: newline in dollar-quote'
54
+  steps:
55
+  - send_line: echo $'line1\nline2'
56
+  expect_output: line1
57
+  match_type: contains
58
+
59
+- name: '2. ESCAPE SEQUENCES: single quote in dollar-quote'
60
+  steps:
61
+  - send_line: echo $'it'\''s fine'
62
+  expect_output: it's fine
63
+  match_type: contains
64
+
65
+- name: '2. ESCAPE SEQUENCES: printf hex'
66
+  steps:
67
+  - send_line: printf '\x41\x42\x43\n'
68
+  expect_output: ABC
69
+  match_type: contains
70
+
71
+- name: '2. ESCAPE SEQUENCES: printf %b hex'
72
+  steps:
73
+  - send_line: printf '%b' '\x41\x42\x43\n'
74
+  expect_output: ABC
75
+  match_type: contains
76
+
77
+- name: '2. ESCAPE SEQUENCES: printf octal'
78
+  steps:
79
+  - send_line: printf '\101\102\103\n'
80
+  expect_output: ABC
81
+  match_type: contains
82
+
83
+- name: '2. ESCAPE SEQUENCES: var@E hex'
84
+  steps:
85
+  - send_line: X='\x48\x69'; echo "${X@E}"
86
+  expect_output: Hi
87
+  match_type: contains
88
+
89
+- name: '2. ESCAPE SEQUENCES: var@E octal'
90
+  steps:
91
+  - send_line: X='\110\151'; echo "${X@E}"
92
+  expect_output: Hi
93
+  match_type: contains
94
+
95
+# ==========================================
96
+# 3. Associative arrays (previously broken on ARM64)
97
+# ==========================================
98
+- name: '3. ASSOC ARRAYS: basic set and get'
99
+  steps:
100
+  - send_line: declare -A m; m[key]=val; echo ${m[key]}
101
+  expect_output: val
102
+  match_type: contains
103
+
104
+- name: '3. ASSOC ARRAYS: multiple keys'
105
+  steps:
106
+  - send_line: declare -A m; m[a]=1; m[b]=2; m[c]=3; echo ${#m[@]}
107
+  expect_output: '3'
108
+  match_type: contains
109
+
110
+- name: '3. ASSOC ARRAYS: overwrite'
111
+  steps:
112
+  - send_line: declare -A m; m[k]=old; m[k]=new; echo ${m[k]}
113
+  expect_output: new
114
+  match_type: contains
115
+
116
+- name: '3. ASSOC ARRAYS: key with spaces'
117
+  steps:
118
+  - send_line: declare -A m; m["hello world"]=yes; echo ${m["hello world"]}
119
+  expect_output: 'yes'
120
+  match_type: contains
121
+
122
+# ==========================================
123
+# 4. Deep nesting
124
+# ==========================================
125
+- name: '4. NESTING: nested command substitution'
126
+  steps:
127
+  - send_line: echo $(echo $(echo $(echo deep)))
128
+  expect_output: deep
129
+  match_type: contains
130
+
131
+- name: '4. NESTING: nested parameter expansion'
132
+  steps:
133
+  - send_line: A=hello; B=A; echo ${!B}
134
+  expect_output: hello
135
+  match_type: contains
136
+
137
+- name: '4. NESTING: nested arithmetic'
138
+  steps:
139
+  - send_line: echo $(( (1 + 2) * (3 + 4) ))
140
+  expect_output: '21'
141
+  match_type: contains
142
+
143
+# ==========================================
144
+# 5. Case transforms (previously broken on macOS)
145
+# ==========================================
146
+- name: '5. CASE TRANSFORMS: uppercase all'
147
+  steps:
148
+  - send_line: X=hello; echo ${X^^}
149
+  expect_output: HELLO
150
+  match_type: contains
151
+
152
+- name: '5. CASE TRANSFORMS: lowercase all'
153
+  steps:
154
+  - send_line: X=HELLO; echo ${X,,}
155
+  expect_output: hello
156
+  match_type: contains
157
+
158
+- name: '5. CASE TRANSFORMS: capitalize first'
159
+  steps:
160
+  - send_line: X=hello; echo ${X^}
161
+  expect_output: Hello
162
+  match_type: contains
163
+
164
+# ==========================================
165
+# 6. C-style for loops
166
+# ==========================================
167
+- name: '6. C-STYLE FOR: basic count'
168
+  steps:
169
+  - send_line: for ((i=0; i<5; i++)); do printf "%d " $i; done; echo
170
+  expect_output: 0 1 2 3 4
171
+  match_type: contains
172
+
173
+- name: '6. C-STYLE FOR: countdown'
174
+  steps:
175
+  - send_line: for ((i=5; i>0; i--)); do printf "%d " $i; done; echo
176
+  expect_output: 5 4 3 2 1
177
+  match_type: contains
178
+
179
+# ==========================================
180
+# 7. Process substitution
181
+# ==========================================
182
+- name: '7. PROCESS SUB: diff two commands'
183
+  steps:
184
+  - send_line: diff <(echo hello) <(echo hello); echo $?
185
+  expect_output: '0'
186
+  match_type: contains
187
+
188
+- name: '7. PROCESS SUB: paste two streams'
189
+  steps:
190
+  - send_line: paste <(echo a) <(echo b)
191
+  expect_output: a
192
+  match_type: contains
193
+
194
+# ==========================================
195
+# 8. Coprocesses
196
+# ==========================================
197
+- name: '8. COPROC: basic brace group'
198
+  steps:
199
+  - send_line: coproc { echo from_coproc; }; read line <&${COPROC[0]}; echo $line
200
+  expect_output: from_coproc
201
+  match_type: contains
202
+  timeout: 5
203
+
204
+# ==========================================
205
+# 9. Brace expansion with step
206
+# ==========================================
207
+- name: '9. BRACE: range with step'
208
+  steps:
209
+  - send_line: echo {1..10..2}
210
+  expect_output: 1 3 5 7 9
211
+  match_type: contains
212
+
213
+- name: '9. BRACE: reverse range'
214
+  steps:
215
+  - send_line: echo {5..1}
216
+  expect_output: 5 4 3 2 1
217
+  match_type: contains
218
+
219
+- name: '9. BRACE: alpha range'
220
+  steps:
221
+  - send_line: echo {a..f}
222
+  expect_output: a b c d e f
223
+  match_type: contains
224
+
225
+# ==========================================
226
+# 10. File tests (previously broken on aarch64)
227
+# ==========================================
228
+- name: '10. FILE TESTS: test -f'
229
+  steps:
230
+  - send_line: touch /tmp/fortsh_pty_test_file; test -f /tmp/fortsh_pty_test_file && echo exists
231
+  expect_output: exists
232
+  match_type: contains
233
+
234
+- name: '10. FILE TESTS: test -d'
235
+  steps:
236
+  - send_line: test -d /tmp && echo isdir
237
+  expect_output: isdir
238
+  match_type: contains
239
+
240
+- name: '10. FILE TESTS: bracket -f'
241
+  steps:
242
+  - send_line: touch /tmp/fortsh_pty_test_file; [ -f /tmp/fortsh_pty_test_file ] && echo exists
243
+  expect_output: exists
244
+  match_type: contains
245
+
246
+- name: '10. FILE TESTS: cleanup'
247
+  steps:
248
+  - send_line: rm -f /tmp/fortsh_pty_test_file; echo cleaned
249
+  expect_output: cleaned
250
+  match_type: contains
251
+
252
+# ==========================================
253
+# 11. ANSI-C quoting
254
+# ==========================================
255
+- name: '11. ANSI-C: backslash literal'
256
+  steps:
257
+  - send_line: echo $'backslash:\\'
258
+  expect_output: 'backslash:'
259
+  match_type: contains
260
+
261
+- name: '11. ANSI-C: double quote in single'
262
+  steps:
263
+  - send_line: echo $'say "hi"'
264
+  expect_output: say "hi"
265
+  match_type: contains
266
+
267
+# ==========================================
268
+# 12. Regex with BASH_REMATCH
269
+# ==========================================
270
+- name: '12. REGEX: basic match'
271
+  steps:
272
+  - send_line: '[[ "hello123" =~ ^([a-z]+)([0-9]+)$ ]] && echo "${BASH_REMATCH[1]} ${BASH_REMATCH[2]}"'
273
+  expect_output: hello 123
274
+  match_type: contains
275
+
276
+# ==========================================
277
+# 13. Here strings
278
+# ==========================================
279
+- name: '13. HERE STRING: basic'
280
+  steps:
281
+  - send_line: cat <<< "hello from here"
282
+  expect_output: hello from here
283
+  match_type: contains
284
+
285
+- name: '13. HERE STRING: with variable'
286
+  steps:
287
+  - send_line: X=world; cat <<< "hello $X"
288
+  expect_output: hello world
289
+  match_type: contains