about summary refs log tree commit diff
path: root/Test/A05execution.ztst
blob: edc5615825c698ceeff729b647086b99ab46f9ea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
%prep

  storepath=($path)

  mkdir command.tmp command.tmp/dir1 command.tmp/dir2

  cd command.tmp

  shcmd="$(which sh)"
  shpath=${shcmd:h}
  echocmd="$(which -p echo)"
  echopath=${echocmd:h}
  print "#!${shcmd}\necho This is top" >tstcmd

  print "#!${shcmd}\necho This is dir1" >dir1/tstcmd

  print "#!${shcmd}\necho This is dir2" >dir2/tstcmd

  print -n '#!sh\necho This is slashless' >tstcmd-slashless
  print -n '#!echo foo\necho This is arg' >tstcmd-arg
  print '#!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnyyy' >tstcmd-interp-too-long
  print "#!${sh}\necho should not execute; exit 1" >xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn

  chmod 755 tstcmd dir1/tstcmd dir2/tstcmd
  chmod 755 tstcmd-slashless tstcmd-arg tstcmd-interp-too-long
  chmod 755 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn

%test
  ./tstcmd
0:./prog execution
>This is top

  path=($ZTST_testdir/command.tmp/dir1
        $ZTST_testdir/command.tmp/dir2
        .)
  tstcmd
  path=($storepath)
0:path (1)
>This is dir1

  path=(. command.tmp/dir{1,2})
  tstcmd
  path=($storepath)
0:path (2)
>This is top

  PATH=${shpath}:${ZTST_testdir}/command.tmp/ tstcmd-slashless
0:path (3)
>This is slashless

  PATH=${echopath}:${ZTST_testdir}/command.tmp tstcmd-arg
0:path (4)
*>foo */command.tmp/tstcmd-arg

  # Just check this exits with non-zero status,
  # as output and status code can differ.
  (
    path=($shpath $echopath ${ZTST_testdir}/command.tmp/)
    if tstcmd-interp-too-long >/dev/null 2>&1; then
      exit 0
    else
      exit 1
    fi
  )
1:path (5)

  functst() { print $# arguments:; print -l $*; }
  functst "Eines Morgens" "als Gregor Samsa"
  functst ""
  functst "aus unrühigen Träumen erwachte"
  foo="fand er sich in seinem Bett"
  bar=
  rod="zu einem ungeheuren Ungeziefer verwandelt."
  functst $foo $bar $rod
# set up alias for next test
  alias foo='print This is alias one'
0:function argument passing
>2 arguments:
>Eines Morgens
>als Gregor Samsa
>1 arguments:
>
>1 arguments:
>aus unrühigen Träumen erwachte
>2 arguments:
>fand er sich in seinem Bett
>zu einem ungeheuren Ungeziefer verwandelt.

  alias foo='print This is alias two'
  fn() { foo; }
  fn
0:Aliases in functions
>This is alias one

  foo='Global foo'
  traptst() { local foo="Local foo"; trap 'print $foo' EXIT; }
  traptst
0:EXIT trap environment
>Global foo

  functst() { return 0; print Ha ha; return 1; }
  functst
0:return (1)

  functst() { return 1; print Ho ho; return 0; }
  functst
1:return (2)

  unfunction functst
  fpath=(.)
  print "print This is functst." >functst
  autoload functst
  functst
0:autoloading (1)
>This is functst.

  unfunction functst
  print "functst() { print This, too, is functst; }; print Hello." >functst
  typeset -fu functst
  functst
  functst
0:autoloading with initialization
>Hello.
>This, too, is functst

  unfunction functst
  print "print Yet another version" >functst
  functst() { autoload -X; }
  functst
0:autoloading via -X
>Yet another version

  chpwd() { print Changed to $PWD; }
  cd .
  unfunction chpwd
0q:chpwd
>Changed to $ZTST_testdir/command.tmp

  chpwd() { print chpwd: changed to $PWD; }
  chpwdfn1()  { print chpwdfn1: changed to $PWD; }
  chpwdfn2()  { print chpwdfn2: changed to $PWD; }
  chpwd_functions=(chpwdfn1 '' chpwdnonexistentfn chpwdfn2)
  cd .
  unfunction chpwd
  unset chpwd_functions
0q:chpwd_functions
>chpwd: changed to $ZTST_testdir/command.tmp
>chpwdfn1: changed to $ZTST_testdir/command.tmp
>chpwdfn2: changed to $ZTST_testdir/command.tmp

# Hard to test periodic, precmd and preexec non-interactively.

  fn() { TRAPEXIT() { print Exit; }; }
  fn
0:TRAPEXIT
>Exit

  unsetopt DEBUG_BEFORE_CMD
  unfunction fn
  print 'TRAPDEBUG() {
      print Line $LINENO
    }
    :
    unfunction TRAPDEBUG
  ' > fn
  autoload fn
  fn
  rm fn
0:TRAPDEBUG
>Line 1
>Line 1

  unsetopt DEBUG_BEFORE_CMD
  unfunction fn
  print 'trap '\''print Line $LINENO'\'' DEBUG
    :
    trap - DEBUG
  ' > fn
  autoload fn
  fn
  rm fn
0:trap DEBUG
>Line 1
>Line 2

  TRAPZERR() { print Command failed; }
  true
  false
  true
  false
  unfunction TRAPZERR
0:TRAPZERR
>Command failed
>Command failed

  trap 'print Command failed again.' ZERR
  true
  false
  true
  false
  trap - ZERR
0:trap ZERR
>Command failed again.
>Command failed again.

  false
  sleep 1000 &
  print $?
  kill $!
0:Status reset by starting a backgrounded command
>0

  { setopt MONITOR } 2>/dev/null
  [[ -o MONITOR ]] || print -u $ZTST_fd 'Unable to change MONITOR option'
  repeat 2048; do (return 2 |
                   return 1 |
                   while true; do
                             false
                             break
                           done;
                   print "${pipestatus[@]}")
	ZTST_hashmark
  done | sort | uniq -c | sed 's/^ *//'
0:Check whether '$pipestatus[]' behaves.
>2048 2 1 0
F:This test checks for a bug in '$pipestatus[]' handling.  If it breaks then
F:the bug is still there or it reappeared. See workers-29973 for details.

  { setopt MONITOR } 2>/dev/null
  externFunc() { awk >/dev/null 2>&1; true; }
  false | true | false | true | externFunc
  echo $pipestatus
0:Check $pipestatus with a known difficult case
>1 0 1 0 0
F:This similar test was triggering a reproducible failure with pipestatus.

  { unsetopt MONITOR } 2>/dev/null
  coproc { read -et 5 || { print -u $ZTST_fd KILLED; kill -HUP -$$ } }
  print -u $ZTST_fd 'This test takes 5 seconds to fail...'
  { printf "%d\n" {1..20000} } 2>/dev/null | ( read -e )
  hang(){ printf "%d\n" {2..20000} | cat }; hang 2>/dev/null | ( read -e )
  print -p done
  read -et 6 -p
0:Bug regression: piping a shell construct to an external process may hang
>1
>2
>done
F:This test checks for a file descriptor leak that could cause the left
F:side of a pipe to block on write after the right side has exited

  { setopt MONITOR } 2>/dev/null
  if [[ -o MONITOR ]]
  then
   ( while :; do print "This is a line"; done ) | () : &
   sleep 1
   jobs -l
  else
   print -u $ZTST_fd "Skipping pipe leak test, requires MONITOR option"
   print "[0] 0 0"
  fi
0:Bug regression: piping to anonymous function; piping to backround function
*>\[<->\] <-> <->
F:This test checks for two different bugs, a parser segfault piping to an
F:anonymous function, and a descriptor leak when backgrounding a pipeline

  print "autoload_redir() { print Autoloaded ksh style; } >autoload.log" >autoload_redir
  autoload -Uk autoload_redir
  autoload_redir
  print No output yet
  cat autoload.log
  functions autoload_redir
0:
>No output yet
>Autoloaded ksh style
>autoload_redir () {
>	print Autoloaded ksh style
>} > autoload.log

# This tests that we record the status of processes that have already exited
# for when we wait for them.
#
# Actually, we don't guarantee here that the jobs have already exited, but
# the order of the waits means it's highly likely we do need to recall a
# previous status, barring accidents which shouldn't happen very often.  In
# other words, we rely on the test working repeatedly rather than just
# once.  The monitor option is irrelevant to the logic, so we'll make
# our job easier by turning it off.
  { unsetopt MONITOR } 2>/dev/null
  (exit 1) &
  one=$!
  (exit 2) &
  two=$!
  (exit 3) &
  three=$!
  wait $three
  print $?
  wait $two
  print $?
  wait $one
  print $?
0:The status of recently exited background jobs is recorded
>3
>2
>1

# Regression test for workers/34060 (patch in 34065)
  setopt ERR_EXIT NULL_GLOB
  if false; then :; else echo if:$?; fi
  if false; then :; else for x in _*_; do :; done; echo for:$?; fi
0:False "if" condition handled correctly by "for" loops with ERR_EXIT
>if:1
>for:0

# Regression test for workers/34065 (uses setopt from preceding test)
  select x; do :; done; echo $?
  select x in; do :; done; echo $?
  select x in _*_; do :; done; echo $?
  unsetopt ERR_EXIT NULL_GLOB
0:The status of "select" is zero when the loop body does not execute
>0
>0
>0

# Regression test for workers/36392
  print -u $ZTST_fd 'This test takes 3 seconds and hangs the shell when it fails...'
  callfromchld() { true && { print CHLD } }
  TRAPCHLD() { callfromchld }
  sleep 2 & sleep 3; print OK
0:Background job exit does not affect reaping foreground job
>CHLD
>OK

# Regression test for workers/39839 and workers/39844
  () { if return 11; then :; fi }; echo $?
  () { while return 13; do :; done }; echo $?
  () { until return 17; do :; done }; echo $?
  () { until false; do return 19; done }; echo $?
0:"return" in "if" or "while" conditional
>11
>13
>17
>19

# Test 'wait' for unknown job/process ID.
  wait 1
  echo $?
  wait %%
  echo $?
  wait %+
  echo $?
  wait %-
  echo $?
  wait %1
  echo $?
  wait %foo
  echo $?
  wait %\?bar
127:'wait' exit status and warning for unknown ID
>127
>127
>127
>127
>127
>127
?(eval):wait:1: pid 1 is not a child of this shell
?(eval):wait:3: %%: no such job
?(eval):wait:5: %+: no such job
?(eval):wait:7: %-: no such job
?(eval):wait:9: %1: no such job
?(eval):wait:11: job not found: foo
?(eval):wait:13: job not found: ?bar

# Test 'wait' for unknown job/process ID (POSIX mode).
  (setopt POSIX_BUILTINS
  wait 1
  echo $?
  wait %%
  echo $?
  wait %+
  echo $?
  wait %-
  echo $?
  wait %1
  echo $?
  wait %foo
  echo $?
  wait %\?bar)
127:'wait' exit status for unknown ID (POSIX mode)
>127
>0
>127
>127
>127
>127
# TBD: the 0 above is believed to be bogus and should also be turned
# into 127 when the ccorresponding bug is fixed in the main shell.