Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH 2/2] Consolidated nofork substitution tests
- X-seq: zsh-workers 52155
- From: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: [PATCH 2/2] Consolidated nofork substitution tests
- Date: Sat, 16 Sep 2023 15:27:37 -0700
- Archived-at: <https://zsh.org/workers/52155>
- List-id: <zsh-workers.zsh.org>
Note the last test (break N propagates) references the as-yet-unfixed
bug from workers/52151.
diff --git a/Test/D10nofork.ztst b/Test/D10nofork.ztst
new file mode 100644
index 000000000..024b8ffcc
--- /dev/null
+++ b/Test/D10nofork.ztst
@@ -0,0 +1,448 @@
+# Tests for "nofork" command substitution.
+
+%prep
+ mkdir nofork.tmp
+ touch nofork.tmp/file{1,2}.txt
+
+ purr() { print -r -- "$@" }
+ purl() { print -rl -- "$@" }
+
+%test
+
+ REPLY=OUTER
+ purr ${| REPLY=INNER } $REPLY
+0:Basic substitution and REPLY scoping
+>INNER OUTER
+
+ purr ${| REPLY=first}:${| REPLY=second}:$REPLY
+0:re-scoping of REPLY in one statement
+>first:second:OUTER
+
+ purr BEGIN${| printf -v REPLY '%s\n' one two three ; }END
+0:Adjacent words
+>BEGINone
+>two
+>three
+>END
+
+ purr "BEGIN${| printf -v REPLY '%s\n' one two three }END"
+0:Adjacent words and quoting, part 1
+>BEGINone
+>two
+>three
+>END
+
+ purr BEGIN"${| printf -v REPLY '%s\n' one two three }"END
+0:Adjacent words and quoting, part 2
+>BEGINone
+>two
+>three
+>END
+
+ purr BEGIN"${|
+ printf -v REPLY '%s\n'\
+ one two three
+ }"END
+0:Embedded newlines
+>BEGINone
+>two
+>three
+>END
+
+ purr BEGIN"${|
+ printf -v REPLY $'%s\n' one two three
+ }"END
+0:Embedded newlines and $'...'
+>BEGINone
+>two
+>three
+>END
+
+ purl ${| print -v REPLY one word here; setopt shwordsplit }
+ purl ${| print -v REPLY three words here }
+ purl "and ${| print -v REPLY one word here }"
+ unsetopt shwordsplit
+0:test word splitting on result
+F:setting option inside is too late for that substitution
+>one word here
+>three
+>words
+>here
+>and one word here
+
+ (
+ cd nofork.tmp
+ setopt globsubst
+ purr ${| REPLY=f* }
+ purr ${| REPLY=f? }*
+ unsetopt globsubst
+ purr ${| REPLY=f* }
+ purr ${| REPLY=f? }*
+ )
+1:globsubst on result
+>file1.txt file2.txt
+>file1.txt file2.txt
+>f*
+?(eval):8: no matches found: f?*
+
+ purr ${| REPLY=$'trailing newlines remain\n\n' }
+0:newline removal should not occur
+>trailing newlines remain
+>
+>
+
+ () {
+ purr ${| REPLY=$* ; shift 2 }
+ purr $*
+ } these are arguments
+0:access to context $argv
+>these are arguments
+>arguments
+
+ purr ${:-${| REPLY=${REPLY:-buried}}}
+ purr ${:-"${| REPLY=${REPLY:-more buried}}"}
+0:nofork inside parameter scope
+>buried
+>more buried
+
+ : ${(e):-'${| REPLY=oops'}
+1:unclosed braces are sometimes a bad substitution
+F:This seems silly, but see A01grammar ${(e):-'${'} test
+?(eval):1: bad substitution
+
+ purr ${| REPLY=oops
+1:other times lack of closing brace is merely unexpected
+F:Why not use this error in the previous case as well?
+?(eval):1: closing brace expected
+
+# Next tests check that the PS2 stack is properly managed on error
+
+ purr ${| REPLY=${REPLY:-buried}}}
+1:unbalanced braces, part 0
+?(eval):1: parse error near `}'
+
+ purr ${:-${| REPLY=${REPLY:-buried}}
+1:unbalanced braces, part 1
+?(eval):1: closing brace expected
+
+ purr ${:-"${| REPLY=${REPLY:-more buried}"}
+1:unbalanced braces, part 2
+?(eval):1: unmatched "
+
+ purr ${:-"${| REPLY=${REPLY:-more buried"}}}
+1:unbalanced braces, part 3
+?(eval):1: unmatched "
+
+ purr ${:-"${| REPLY=${REPLY:-more buried}}}"
+1:unbalanced braces, part 4
+?(eval):1: closing brace expected
+
+# Same tests with leading space (future-proofing)
+
+ purr ${ purr ${REPLY:-buried}}}
+1:unbalanced braces, part 0+
+?(eval):1: parse error near `}'
+
+ purr ${:-${ purr ${REPLY:-buried}}
+1:unbalanced braces, part 1+
+?(eval):1: closing brace expected
+
+ purr ${:-"${ purr ${REPLY:-more buried}"}
+1:unbalanced braces, part 2+
+?(eval):1: unmatched "
+
+ purr ${:-"${ purr ${REPLY:-more buried"}}}
+1:unbalanced braces, part 3+
+?(eval):1: unmatched "
+
+ purr ${:-"${ purr ${REPLY:-more buried}}}"
+1:unbalanced braces, part 4+
+?(eval):1: closing brace expected
+
+ purr ${ purr STDOUT }
+0:capture stdout
+>STDOUT
+>
+
+# end PS2 stack tests
+
+ purr $(purr outside ${| REPLY=inside })
+ purr BEGIN$(purr outside ${| REPLY=inside })END
+ purr "BEGIN$(purr outside ${| REPLY=inside })END"
+ purr outside ${| REPLY=$(purr inside)}
+ purr "outside ${| REPLY=$(purr inside)}"
+0:mixing with forking cmdsubst
+>outside inside
+>BEGINoutside insideEND
+>BEGINoutside insideEND
+>outside inside
+>outside inside
+
+ purr `purr outside ${| REPLY=inside }`
+ purr "outside `purr ${| REPLY=inside }`"
+ purr outside ${| REPLY=`purr inside`}
+ purr "outside ${| REPLY=`purr inside`}"
+ purr outside "`purr ${| REPLY="${:-inside}"}`"
+ purr "outside ${| REPLY=`purr ${:-inside}`}"
+0:mixing with backticks
+>outside inside
+>outside inside
+>outside inside
+>outside inside
+>outside inside
+>outside inside
+
+ purr ${| REPLY=$(( 9 + 17 )) }
+ purr $(( 9 + ${| REPLY=17 } ))
+0:mixing with arithemetic
+>26
+>26
+
+ unset reply
+ purl ${|reply| reply=(1 2 ${| REPLY=3 } 4) }
+ typeset -p reply
+0:array behavior with global assignment
+>1
+>2
+>3
+>4
+>typeset -g -a reply=( 1 2 3 4 )
+
+ unset outer
+ purr "${|
+ outer=OUTER
+ REPLY=INNER
+ return 7
+ OUTER=NOTREACHED
+ } $outer $?"
+0:return statement inside, part 1
+F:status of "print" should hide return
+>INNER OUTER 7
+
+ unset outer
+ outer=${| REPLY=${| return 7}}
+7:return status propages in assignment like $(...)
+
+ unset outer
+ purr "${|
+ outer=OUTER
+ REPLY=INNER
+ return 7
+ OUTER=NOTREACHED
+ } $outer $?"
+ print REACHED $OUTER
+0:return statement inside, part 2
+>INNER OUTER 7
+>REACHED
+
+ unset outer
+ purr "${|
+ # Localoptions needed to avoid breaking test harness?
+ # The setopt command affects surrounding context
+ setopt localoptions errreturn
+ outer=OUTER
+ REPLY=INNER
+ false
+ OUTER=NOTREACHED
+ } $outer $?"
+ print REACHED $OUTER ${options[errreturn]}
+0:errreturn works inside and remains outside
+>INNER OUTER 1
+>REACHED on
+
+ (
+ unset outer
+ purr "${|
+ outer=OUTER
+ REPLY=INNER
+ exit 7
+ OUTER=NOTREACHED
+ } $outer $OUTER $?"
+ print NOT REACHED
+ )
+7:exit statement inside
+
+ (
+ unset outer
+ purr "${|
+ setopt errexit
+ outer=OUTER
+ REPLY=INNER
+ false
+ OUTER=NOTREACHED
+ } $outer $?"
+ print NOT REACHED
+ )
+1:errexit inside
+
+ outer=GLOBAL
+ purr "${|
+ local outer=LOCAL
+ REPLY=INNER
+ } $outer $?"
+0:local declaration inside
+>INNER GLOBAL 0
+
+ unset zz
+ outer=GLOBAL
+ purr "${|zz|
+ local outer=LOCAL
+ zz=NONLOCAL
+ } $outer $?"
+ print $zz
+0:local declaration, global assignment, part 1
+>NONLOCAL GLOBAL 0
+>NONLOCAL
+
+ unset zz
+ outer=GLOBAL
+ purr "${${|
+ local outer=LOCAL
+ zz=NONLOCAL
+ }:-$zz} $outer $?"
+0:local declaration, global assignment, part 2 (evaluation order)
+>NONLOCAL GLOBAL 0
+
+ : ${| fn1() { () { print -v REPLY $'Defined Function' ;} ;} }
+ print "IN${| fn2() { () { print "${:-Second }${|fn1}" ;} ;} }OUT"
+ fn2
+0:function definition, brace nesting, quote nesting
+>INOUT
+>Second Defined Function
+
+ <<-EOF
+ ${| REPLY=$'in a here document\n' }
+ EOF
+0:here-document behavior
+F:Fiddly here to get EOF past the test syntax
+>in a here document
+>
+
+ <<<${| REPLY="in a here string" }
+0:here-string behavior
+>in a here string
+
+ <<<${ purr $'stdout as a here string' }
+0:another capture stdout
+>stdout as a here string
+>
+
+ wrap=${| REPLY="REPLY in environment assignment" } typeset -p wrap
+ wrap=${ purr "capture in environment assignment" } typeset -p wrap
+0:assignment context
+>typeset -g wrap='REPLY in environment assignment'
+>typeset -g wrap=$'capture in environment assignment\n'
+
+# Repeat return and exit tests with stdout capture
+
+ purr "${
+ print INNER
+ return 7
+ } $?"
+0:return statement inside, part 1+
+F:status of "print" should hide return
+>INNER
+> 7
+
+ unset outer
+ outer=${ return 7 }
+7:return status propages in stdout capture
+
+ unset outer
+ purr "${
+ outer=OUTER
+ print INNER
+ return 7
+ OUTER=NOTREACHED
+ } $outer $?"
+ print REACHED $OUTER
+0:return statement inside, part 2+
+>INNER
+> OUTER 7
+>REACHED
+
+ unset outer
+ purr "${
+ # Localoptions needed to avoid breaking test harness?
+ # The setopt command affects surrounding context
+ setopt localoptions errreturn
+ outer=OUTER
+ print INNER
+ false
+ OUTER=NOTREACHED
+ } $outer $?"
+ print REACHED $OUTER ${options[errreturn]}
+0:errreturn works inside stdout capture
+>INNER
+> OUTER 1
+>REACHED on
+
+ (
+ unset outer
+ purr "${
+ outer=OUTER
+ print INNER
+ exit 7
+ OUTER=NOTREACHED
+ } $outer $OUTER $?"
+ print NOT REACHED
+ )
+7:exit statement inside stdout capture
+
+ (
+ unset outer
+ purr "${
+ setopt errexit
+ outer=OUTER
+ print INNER
+ false
+ OUTER=NOTREACHED
+ } $outer $?"
+ print NOT REACHED
+ )
+1:errexit inside stdout capture
+
+ setopt ignorebraces
+0:dummy test to set option soon enough
+F:must do this before evaluating the next test block
+
+ purr ${| REPLY=${REPLY:-buried}}}
+0:ignored braces, part 1
+>buried}
+
+ purr ${ purr ${REPLY:-buried}}}
+0:ignored braces, part 2
+>buried
+>}
+
+ purr ${ { echo nested ;} }
+0:ignored braces, part 3
+>nested
+>
+
+ purr ${ { echo nested } } DONE
+1:ignored braces, part 4
+?(eval):1: parse error near `}'
+
+ # "break" blocks function calls in outer loop
+ # Could use print, but that might get fixed
+ repeat 3 do purr ${
+ for x in 1 2 3 4
+ do (( x == 3 )) && break 2
+ # use error output to confirm loop count
+ print -u 2 $x
+ done
+ } XX
+ done
+0:break N propagates
+?1
+?2
+
+ print -u $ZTST_fd ${ZTST_testname}: TEST COMPLETE
+0:make sure we got to the end
+F:some tests might silently break the test harness
+
+%clean
+
+ unfunction purr purl
+ unsetopt ignorebraces
Messages sorted by:
Reverse Date,
Date,
Thread,
Author