about summary refs log tree commit diff
path: root/Test
diff options
context:
space:
mode:
authorPaul Ackersviller <packersv@users.sourceforge.net>2007-11-18 21:57:32 +0000
committerPaul Ackersviller <packersv@users.sourceforge.net>2007-11-18 21:57:32 +0000
commit95b4d6a31f5255987db5f8005f557bb63aa3a2cb (patch)
treef3c2a3f0ec252949cb776c8795dbb0de0b60a01d /Test
parent083359cd89d28415a909402e7f69708bb3a32aaa (diff)
downloadzsh-95b4d6a31f5255987db5f8005f557bb63aa3a2cb.tar.gz
zsh-95b4d6a31f5255987db5f8005f557bb63aa3a2cb.tar.xz
zsh-95b4d6a31f5255987db5f8005f557bb63aa3a2cb.zip
Merge of 23460/23461: fix longstanding problem with multios attached to a subshell process.
Diffstat (limited to 'Test')
-rw-r--r--Test/E01options.ztst1012
1 files changed, 1012 insertions, 0 deletions
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
new file mode 100644
index 000000000..da75f98ee
--- /dev/null
+++ b/Test/E01options.ztst
@@ -0,0 +1,1012 @@
+# Test various shell options.
+# Interactive options not tested here:
+#    ALWAYS_LAST_PROMPT
+#    ALWAYS_TO_END
+#    APPEND_HISTORY (history not maintained)
+#    AUTO_LIST
+#    AUTO_MENU
+#    AUTO_NAME_DIRS  (named directory table not maintained)
+#    AUTO_PARAM_KEYS
+#    AUTO_PARAM_SLASH
+#    AUTO_REMOVE_SLASH
+#    AUTO_RESUME
+#    BANG_HIST
+#    BASH_AUTO_LIST
+#    BEEP (!)
+#    BG_NICE
+#    CHECK_JOBS
+#    COMPLETE_ALIASES
+#    COMPLETE_IN_WORD
+#    CORRECT
+#    CORRECT_ALL
+#    CSH_JUNKIE_HISTORY
+#    DVORAK
+#    EXTENDED_HISTORY
+#    FLOW_CONTROL
+#    GLOB_COMPLETE
+#    HIST_ALLOW_CLOBBER
+#    HIST_BEEP
+#    HIST_EXPIRE_DUPS_FIRST
+#    HIST_FIND_NO_DUPS
+#    HIST_IGNORE_ALL_DUPS
+#    HIST_IGNORE_DUPS (-h)
+#    HIST_IGNORE_SPACE (-g)
+#    HIST_NO_FUNCTIONS
+#    HIST_NO_STORE
+#    HIST_REDUCE_BLANKS
+#    HIST_SAVE_NO_DUPS
+#    HIST_VERIFY
+#    HUP
+#    IGNORE_EOF
+#    INC_APPEND_HISTORY
+#    INTERACTIVE
+#    INTERACTIVE_COMMENTS
+#    LIST_AMBIGUOUS
+#    LIST_BEEP
+#    LIST_PACKED
+#    LIST_ROWS_FIRST
+#    LIST_TYPES
+#    LOGIN
+#    LONG_LIST_JOBS
+#    MAIL_WARNING
+#    MENU_COMPLETE
+#    MONITOR
+#    NOTIFY
+#    OVERSTRIKE
+#    PRINT_EIGHT_BIT
+#    PROMPT_CR
+#    PUSHD_SILENT
+#    REC_EXACT
+#    RM_STAR_SILENT
+#    RM_STAR_WAIT
+#    SHARE_HISTORY
+#    SINGLE_LINE_ZLE
+#    SUN_KEYBOARD_HACK
+#    ZLE
+# The following require SHINSTDIN and are not (yet) tested:
+#    AUTO_CD
+#    SHINSTDIN
+#
+# Other difficult things I haven't done:
+#    GLOBAL_RCS (uses fixed files outside build area)
+#    HASH_CMDS     )
+#    HASH_DIRS     )  fairly seriously internal, hard to test at all
+#    HASH_LIST_ALL )
+#    PRINT_EXIT_STATUS   haven't worked out what this does yet, although
+#                        Bart suggested a fix.
+#    PRIVILEGED (similar to GLOBAL_RCS)
+#    RCS        (  "      "    "    " )
+#    SH_OPTION_LETTERS   even I found this too dull to set up a test for
+#    SINGLE_COMMAND      kills shell
+#    VERBOSE             hard because done on input (c.f. SHINSTDIN).
+
+%prep
+  mkdir options.tmp && cd options.tmp
+
+  mkdir tmpcd
+
+  touch tmpfile1 tmpfile2
+
+  mydir=$PWD
+  mydirt=`print -P %~`
+  catpath=$(which cat)
+  lspath==ls
+
+%test
+
+  alias echo='print foo'
+  unsetopt aliases
+  # use eval else aliases are all parsed at start
+  eval echo bar
+  setopt aliases
+  eval echo bar
+  unalias echo
+0:ALIASES option
+>bar
+>foo bar
+
+  setopt allexport
+  testpm1=exported
+  unsetopt allexport
+  testpm2=unexported
+  print ${(t)testpm1}
+  print ${(t)testpm2}
+0:ALL_EXPORT option
+>scalar-export
+>scalar
+  
+  # Count the number of directories on the stack.  Don't care what they are.
+  dircount() { dirs -v | tail -1 | awk '{ print $1 + 1}'; }
+  unsetopt autopushd
+  cd tmpcd
+  dircount
+  cd ..
+  setopt autopushd
+  cd tmpcd
+  dircount
+  unsetopt autopushd
+  popd >/dev/null
+0:AUTO_PUSHD option
+>1
+>2
+
+  unsetopt badpattern
+  print [a
+  setopt badpattern
+  print [b
+1:BAD_PATTERN option
+>[a
+?(eval):4: bad pattern: [b
+
+  unsetopt bareglobqual nomatch
+  print *(.)
+  setopt bareglobqual nomatch
+  print *(.)
+0:BARE_GLOB_QUAL option
+>*(.)
+>tmpfile1 tmpfile2
+
+  setopt braceccl
+  print {abcd}
+  unsetopt braceccl
+  print {abcd}
+0:BRACE_CCL option
+>a b c d
+>{abcd}
+
+# Don't use NUL as a field separator in the following.
+  setopt braceccl
+  print {$'\0'-$'\5'} | IFS=' ' read -A chars
+  for c in $chars; do print $(( #c )); done
+  unsetopt braceccl
+0:BRACE_CCL option starting from NUL
+>0
+>1
+>2
+>3
+>4
+>5
+
+  setopt bsdecho
+  echo "histon\nimpington"
+  echo -e "girton\ncottenham"
+  unsetopt bsdecho
+  echo "newnham\ncomberton"
+0:BSD_ECHO option
+>histon\nimpington
+>girton
+>cottenham
+>newnham
+>comberton
+
+  unsetopt c_bases
+  print $(( [#16]15 ))
+  print $(( [#8]9 ))
+  setopt c_bases
+  print $(( [#16]31 ))
+  print $(( [#8]17 ))
+  setopt octal_zeroes
+  print $(( [#8]19 ))
+  unsetopt c_bases octal_zeroes
+0:C_BASES option
+>16#F
+>8#11
+>0x1F
+>8#21
+>023
+
+  setopt cdablevars
+  # only absolute paths are eligible for ~-expansion
+  cdablevar1=tmpcd
+  (cd cdablevar1)
+  cdablevar2=$PWD/tmpcd
+  cd cdablevar2
+  cd ..
+  print back in ${PWD:t}
+  unsetopt cdablevars
+  cd cdablevar2
+1q:CDABLE_VARS option
+>back in options.tmp
+?(eval):cd:4: no such file or directory: cdablevar1
+?(eval):cd:10: no such file or directory: cdablevar2
+
+# CHASE_DOTS should go with CHASE_LINKS in B01cd.ztst
+# which saves me having to write it here.
+
+  setopt noclobber
+  rm -f foo1 bar1 rod1
+  echo waterbeach >foo1
+  (echo landbeach >foo1)
+  cat foo1
+  (echo lode >>bar1)
+  [[ -f bar1 ]] && print That shouldn\'t be there.
+  echo denny >rod1
+  echo wicken >>rod1
+  cat rod1
+  unsetopt noclobber
+  rm -f foo2 bar2 rod2
+  echo ely >foo2
+  echo march >foo2
+  cat foo2
+  echo wimpole >>bar2
+  cat bar2
+  echo royston >rod2
+  echo foxton >>rod2
+  cat rod2
+  rm -f foo* bar* rod*
+0:CLOBBER option
+>waterbeach
+>denny
+>wicken
+>march
+>wimpole
+>royston
+>foxton
+?(eval):4: file exists: foo1
+?(eval):6: no such file or directory: bar1
+
+   setopt cshjunkieloops
+   eval 'for f in swaffham bulbeck; print $f; end'
+   print next one should fail >&2
+   unsetopt cshjunkieloops
+   eval 'for f in chesterton arbury; print $f; end'
+1:CSH_JUNKIE_LOOPS option (for loop)
+>swaffham
+>bulbeck
+?next one should fail
+?(eval):1: parse error near `end'
+
+  setopt cshjunkiequotes
+  print this should cause an error >&2
+  eval "print 'line one
+  line two'"
+  print this should not >&2
+  eval "print 'line three\\
+  line four'"
+  unsetopt cshjunkiequotes
+0:CSH_JUNKIE_QUOTES option
+>line three
+>  line four
+?this should cause an error
+?(eval):1: unmatched '
+?this should not
+
+  nullcmd() { print '$NULLCMD run'; }
+  readnullcmd() { print 'Running $READNULLCMD'; cat; }
+  NULLCMD=nullcmd
+  READNULLCMD=readnullcmd
+  setopt cshnullcmd
+  rm -f foo
+  print "This should fail" >&2
+  (>foo)
+  print "This should succeed" >&2
+  print "These are the contents of foo" >foo
+  cat foo
+  print "This should also fail" >&2
+  (<foo)
+  unsetopt cshnullcmd
+  rm -f foo
+  >foo
+  <foo
+  rm -f foo
+0:CSH_NULL_CMD option
+>These are the contents of foo
+>Running $READNULLCMD
+>$NULLCMD run
+?This should fail
+?(eval):8: redirection with no command
+?This should succeed
+?This should also fail
+?(eval):13: redirection with no command
+
+# nomatch should be overridden by cshnullglob
+  setopt nomatch cshnullglob
+  print tmp* nothing* blah
+  print -n 'hoping for no match: ' >&2
+  (print nothing* blah)
+  print >&2
+  unsetopt cshnullglob nomatch
+  print tmp* nothing* blah
+  print nothing* blah
+0:CSH_NULL_GLOB option
+>tmpcd tmpfile1 tmpfile2 blah
+>tmpcd tmpfile1 tmpfile2 nothing* blah
+>nothing* blah
+?hoping for no match: (eval):4: no match
+?
+
+# The trick is to avoid =cat being expanded in the output while $catpath is.
+  setopt NO_equals
+  print -n trick; print =cat
+  setopt equals
+  print -n trick; print =cat
+0q:EQUALS option
+>trick=cat
+>trick$catpath
+
+# explanation of expected TRAPZERR output:  from false and from
+# testfn() with ERR_EXIT on (hmm, should we really get a second one from
+# the function exiting?), then from the false only with ERR_EXIT off.
+  TRAPZERR() { print ZERR trapped; }
+  testfn() { setopt localoptions $2; print $1 before; false; print $1 after; }
+  (testfn on errexit)
+  testfn off
+  unfunction TRAPZERR testfn
+0:ERR_EXIT option
+>on before
+>ZERR trapped
+>ZERR trapped
+>off before
+>ZERR trapped
+>off after
+
+  (print before; setopt noexec; print after)
+0:NO_EXEC option
+>before
+
+  setopt NO_eval_lineno
+  eval 'print $LINENO'
+  setopt eval_lineno
+  eval 'print $LINENO'
+0:EVAL_LINENO option
+>2
+>1
+
+  # The EXTENDED_GLOB test doesn't test globbing fully --- it just tests
+  # that certain patterns are treated literally with the option off
+  # and as patterns with the option on.
+  testfn() { print -n "$1 $2 $3 "; if [[ $1 = ${~2} ]];
+             then print yes; else print no; fi; }
+  tests=('a#' '?~b' '^aa')
+  strings=('a' 'aa' 'b' 'a#' '?~b' '^aa')
+  for opt in noextendedglob extendedglob; do
+    setopt $opt
+    for test in $tests; do
+      for string in $strings; do
+         testfn $string $test $opt
+      done
+    done
+  done
+0:EXTENDED_GLOB option
+>a a# noextendedglob no
+>aa a# noextendedglob no
+>b a# noextendedglob no
+>a# a# noextendedglob yes
+>?~b a# noextendedglob no
+>^aa a# noextendedglob no
+>a ?~b noextendedglob no
+>aa ?~b noextendedglob no
+>b ?~b noextendedglob no
+>a# ?~b noextendedglob no
+>?~b ?~b noextendedglob yes
+>^aa ?~b noextendedglob no
+>a ^aa noextendedglob no
+>aa ^aa noextendedglob no
+>b ^aa noextendedglob no
+>a# ^aa noextendedglob no
+>?~b ^aa noextendedglob no
+>^aa ^aa noextendedglob yes
+>a a# extendedglob yes
+>aa a# extendedglob yes
+>b a# extendedglob no
+>a# a# extendedglob no
+>?~b a# extendedglob no
+>^aa a# extendedglob no
+>a ?~b extendedglob yes
+>aa ?~b extendedglob no
+>b ?~b extendedglob no
+>a# ?~b extendedglob no
+>?~b ?~b extendedglob no
+>^aa ?~b extendedglob no
+>a ^aa extendedglob yes
+>aa ^aa extendedglob no
+>b ^aa extendedglob yes
+>a# ^aa extendedglob yes
+>?~b ^aa extendedglob yes
+>^aa ^aa extendedglob yes
+
+  foo() { print My name is $0; }
+  unsetopt functionargzero
+  foo
+  setopt functionargzero
+  foo
+  unfunction foo
+0:FUNCTION_ARGZERO option
+>My name is ZTST_execchunk
+>My name is foo
+
+  setopt _NO_glob_
+  print tmp*
+  set -o glob
+  print tmp*
+0:GLOB option
+>tmp*
+>tmpcd tmpfile1 tmpfile2
+
+  showit() { local v;
+             for v in first second third; do
+               eval print \$$v \$\{\(t\)$v\}
+	     done;
+           }      
+  setit() { typeset -x first=inside1;
+            typeset +g -x second=inside2;
+            typeset -g -x third=inside3;
+            showit;
+          }
+  first=outside1 second=outside2 third=outside3
+  unsetopt globalexport
+  setit
+  showit
+  setopt globalexport
+  setit
+  showit
+  unfunction setit showit
+0:GLOBAL_EXPORT option
+>inside1 scalar-local-export
+>inside2 scalar-local-export
+>inside3 scalar-export
+>outside1 scalar
+>outside2 scalar
+>inside3 scalar-export
+>inside1 scalar-export
+>inside2 scalar-local-export
+>inside3 scalar-export
+>inside1 scalar-export
+>outside2 scalar
+>inside3 scalar-export
+
+  setopt globassign
+  foo=tmp*
+  print $foo
+  unsetopt globassign
+  foo=tmp*
+  print $foo
+0:GLOB_ASSIGN option
+>tmpcd tmpfile1 tmpfile2
+>tmp*
+
+  mkdir onlysomefiles
+  touch onlysomefiles/.thisfile onlysomefiles/thatfile
+  setopt globdots
+  print onlysomefiles/*
+  unsetopt globdots
+  print onlysomefiles/*
+  rm -rf onlysomefiles
+0:GLOB_DOTS option
+>onlysomefiles/.thisfile onlysomefiles/thatfile
+>onlysomefiles/thatfile
+
+  # we've tested this enough times already...
+  # could add some stuff for other sorts of expansion
+  foo='tmp*'
+  setopt globsubst
+  print ${foo}
+  unsetopt globsubst
+  print ${foo}
+0:GLOB_SUBST option
+>tmpcd tmpfile1 tmpfile2
+>tmp*
+
+  setopt ignorebraces
+  echo X{a,b}Y
+  unsetopt ignorebraces
+  echo X{a,b}Y
+0:IGNORE_BRACES option
+>X{a,b}Y
+>XaY XbY
+
+  setopt ksh_arrays
+  array=(one two three)
+  print $array $array[2]
+  print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
+  unsetopt ksh_arrays
+  print $array $array[2]
+  print ${array[0]} ${array[1]} ${array[2]} ${array[3]}
+  unset array
+0:KSH_ARRAYS option
+>one one[2]
+>one two three
+>one two three two
+>one one two three
+
+  fpath=(.)
+  echo >foo 'echo foo loaded; foo() { echo foo run; }'
+  echo >bar 'bar() { echo bar run; }'
+  setopt kshautoload
+  autoload foo bar
+  foo
+  bar
+  unfunction foo bar
+  unsetopt kshautoload
+  autoload foo bar
+  foo
+  bar
+0:KSH_AUTOLOAD option
+>foo loaded
+>foo run
+>bar run
+>foo loaded
+>bar run
+
+# ksh_glob is tested by the glob tests.
+
+  setopt kshoptionprint globassign
+  print set
+  setopt | grep kshoptionprint
+  setopt | grep globassign
+  unsetopt kshoptionprint
+  print unset
+  setopt | grep kshoptionprint
+  setopt | grep globassign
+  unsetopt globassign
+0:KSH_OPTION_PRINT option
+>set
+>kshoptionprint        on
+>globassign            on
+>unset
+>globassign
+
+  setopt kshtypeset
+  ktvars=(ktv1 ktv2)
+  typeset ktfoo=`echo arg1 arg2` $ktvars
+  print $+ktv1 $+ktv2 $+ktv3
+  print $ktfoo
+  unsetopt kshtypeset
+  typeset noktfoo=`echo noktarg1 noktarg2`
+  print $noktfoo
+  print $+noktarg1 $+noktarg2
+  unset ktfoo ktv1 ktv2 noktfoo noktarg2
+0:KSH_TYPESET option
+>1 1 0
+>arg1 arg2
+>noktarg1
+>0 1
+
+  showopt() { setopt | egrep 'localoptions|ksharrays'; }
+  f1() { setopt localoptions ksharrays; showopt }
+  f2() { setopt ksharrays; showopt }
+  setopt kshoptionprint
+  showopt
+  f1
+  showopt
+  f2
+  showopt
+  unsetopt ksh_arrays
+0:LOCAL_OPTIONS option
+>ksharrays             off
+>localoptions          off
+>ksharrays             on
+>localoptions          on
+>ksharrays             off
+>localoptions          off
+>ksharrays             on
+>localoptions          off
+>ksharrays             on
+>localoptions          off
+
+# LOCAL_TRAPS was tested in C03traps (phew).
+
+  fn() {
+    local HOME=/any/old/name
+    print -l var=~ 'anything goes/here'=~ split=`echo maybe not`;
+  }
+  setopt magicequalsubst
+  fn
+  setopt kshtypeset
+  fn
+  unsetopt magicequalsubst kshtypeset
+  fn
+0:MAGIC_EQUAL_SUBST option
+>var=/any/old/name
+>anything goes/here=/any/old/name
+>split=maybe
+>not
+>var=/any/old/name
+>anything goes/here=/any/old/name
+>split=maybe not
+>var=~
+>anything goes/here=~
+>split=maybe
+>not
+
+  setopt MARK_DIRS
+  print tmp*
+  unsetopt MARK_DIRS
+  print tmp*
+0:MARK_DIRS option
+>tmpcd/ tmpfile1 tmpfile2
+>tmpcd tmpfile1 tmpfile2
+
+# maybe should be in A04redirect
+  print "This is in1" >in1
+  print "This is in2" >in2
+  unsetopt multios
+  print Test message >foo1 >foo2
+  print foo1: $(<foo1)
+  print foo2: $(<foo2)
+  cat <in1 <in2
+  setopt multios
+  print Test message >foo1 >foo2
+  sleep 1   # damn, race in multios
+  print foo1: $(<foo1)
+  print foo2: $(<foo2)
+  cat <in1 <in2
+  rm -f foo1 foo2 in1 in2
+0:MULTIOS option
+>foo1:
+>foo2: Test message
+>This is in2
+>foo1: Test message
+>foo2: Test message
+>This is in1
+>This is in2
+
+# This is trickier than it looks.  There's a hack at the end of
+# execcmd() to catch the multio processes attached to the
+# subshell, which otherwise sort of get lost in the general turmoil.
+# Without that, the multios aren't synchronous with the subshell
+# or the main shell starting the "cat", so the output files appear
+# empty.
+  setopt multios
+  ( echo hello ) >multio_out1 >multio_out2 && cat multio_out*
+0:Multios attached to a subshell
+>hello
+>hello
+
+# This tests for another race in multios.
+  print 'This test hangs the shell when it fails...' >&8
+  setopt multios
+  echo These are the contents of the file >multio_race.out
+  multio_race_fn() { cat; }
+  multio_race_fn <$(echo multio_race.out multio_race.out)
+0:Fix for race with input multios
+>These are the contents of the file
+>These are the contents of the file
+
+# tried this with other things, but not on its own, so much.
+  unsetopt nomatch
+  print with nonomatch: flooble*
+  setopt nomatch
+  print with nomatch flooble*
+1:NOMATCH option
+>with nonomatch: flooble*
+?(eval):4: no matches found: flooble*
+
+# NULL_GLOB should override NONOMATCH...
+  setopt nullglob nomatch
+  print frooble* tmp*
+  unsetopt nullglob nomatch
+  print frooble* tmp*
+0:NULL_GLOB option
+>tmpcd tmpfile1 tmpfile2
+>frooble* tmpcd tmpfile1 tmpfile2
+
+  touch ngs1.txt ngs2.txt ngs10.txt ngs20.txt ngs100.txt ngs200.txt
+  setopt numericglobsort
+  print -l ngs*
+  unsetopt numericglobsort
+  print -l ngs*
+0:NUMERIC_GLOB_SORT option
+>ngs1.txt
+>ngs2.txt
+>ngs10.txt
+>ngs20.txt
+>ngs100.txt
+>ngs200.txt
+>ngs1.txt
+>ngs10.txt
+>ngs100.txt
+>ngs2.txt
+>ngs20.txt
+>ngs200.txt
+
+  typeset -i 10 oznum
+  setopt octalzeroes
+  (( oznum = 012 + 013 ))
+  print $oznum
+  unsetopt octalzeroes
+  (( oznum = 012 + 013 ))
+  print $oznum
+  unset oznum
+0:OCTAL_ZEROES options
+>21
+>25
+
+  typeset -a oldpath
+  oldpath=($path)
+  mkdir pdt_topdir pathtestdir pdt_topdir/pathtestdir
+  print "#!/bin/sh\necho File in upper dir" >pathtestdir/findme
+  print "#!/bin/sh\necho File in lower dir" >pdt_topdir/pathtestdir/findme
+  chmod u+x pathtestdir/findme pdt_topdir/pathtestdir/findme
+  pathtestdir/findme
+  rm -f pathtestdir/findme
+  setopt pathdirs
+  path=($PWD $PWD/pdt_topdir)
+  pathtestdir/findme
+  print unsetting option...
+  unsetopt pathdirs
+  pathtestdir/findme
+  path=($oldpath)
+  unset $oldpath
+  rm -rf pdt_topdir pathtestdir
+0:PATH_DIRS option
+>File in upper dir
+>File in lower dir
+>unsetting option...
+?(eval):14: no such file or directory: pathtestdir/findme
+
+  setopt posixbuiltins
+  PATH= command -v print
+  PATH= command -V print
+  PATH= command print foo
+  unsetopt posixbuiltins
+  print unsetting...
+  PATH= command -V print
+  PATH= command print foo
+127:POSIX_BUILTINS option
+>print
+>print is a shell builtin
+>foo
+>unsetting...
+>print is a shell builtin
+?(eval):8: command not found: print
+
+# This option seems to be problematic.  I don't quite know how it works.
+##   func() {
+##     setopt localoptions printexitvalue
+##     false
+##   }
+##   func
+## 1:PRINT_EXIT_VALUE option
+## ?(eval):2: exit 1
+
+  setopt promptbang
+  print -P !
+  setopt nopromptbang
+  print -P !
+0:PROMPT_BANG option
+>0
+>!
+
+  unsetopt promptpercent
+  print -P '%/'
+  setopt promptpercent
+  print -P '%/'
+0q:PROMPT_PERCENT option
+>%/
+>$mydir
+
+  setopt promptsubst
+  print -P '`echo waaah`'
+  unsetopt promptsubst
+  print -P '`echo waaah`'
+0:PROMPT_SUBST option
+>waaah
+>`echo waaah`
+
+  dirs
+  pushd $mydir/tmpcd
+  dirs
+  pushd $mydir/tmpcd
+  dirs
+  setopt pushdignoredups
+  pushd $mydir/tmpcd
+  dirs
+  unsetopt pushdignoredups
+  popd >/dev/null
+  popd >/dev/null
+0q:PUSHD_IGNOREDUPS option
+>$mydirt
+>$mydirt/tmpcd $mydirt
+>$mydirt/tmpcd $mydirt/tmpcd $mydirt
+>$mydirt/tmpcd $mydirt/tmpcd $mydirt
+
+  mkdir newcd
+  cd $mydir
+  pushd $mydir/tmpcd
+  pushd $mydir/newcd
+  dirs
+  pushd -0
+  dirs
+  setopt pushdminus pushdsilent
+  pushd -0
+  dirs
+  unsetopt pushdminus
+  popd >/dev/null
+  popd >/dev/null
+  cd $mydir  
+0q:PUSHD_MINUS option
+>$mydirt/newcd $mydirt/tmpcd $mydirt
+>$mydirt $mydirt/newcd $mydirt/tmpcd
+>$mydirt $mydirt/newcd $mydirt/tmpcd
+
+# Do you have any idea how dull this is?
+
+  pushd $mydir/tmpcd
+  pushd
+  dirs
+  setopt pushdtohome
+  pushd
+  dirs
+  unsetopt pushdtohome
+  popd
+  pushd
+  popd
+  dirs
+0q:PUSHD_TO_HOME option
+>$mydirt $mydirt/tmpcd
+>~ $mydirt $mydirt/tmpcd
+>$mydirt
+
+  array=(one two three four)
+  setopt rcexpandparam
+  print aa${array}bb
+  unsetopt rcexpandparam
+  print aa${array}bb
+0:RC_EXPAND_PARAM option
+>aaonebb aatwobb aathreebb aafourbb
+>aaone two three fourbb
+
+  setopt rcquotes
+  # careful, this is done when parsing a complete block
+  eval "print 'one''quoted''expression'"
+  unsetopt rcquotes
+  eval "print 'another''quoted''expression'"
+0:RC_QUOTES option
+>one'quoted'expression
+>anotherquotedexpression
+
+# too lazy to test jobs -Z and ARGV0.
+  (setopt restricted; cd /)
+  (setopt restricted; PATH=/bin:/usr/bin)
+  (setopt restricted; /bin/ls)
+  (setopt restricted; hash ls=/bin/ls)
+  (setopt restricted; print ha >outputfile)
+  (setopt restricted; exec ls)
+  (setopt restricted; unsetopt restricted)
+  :
+0:RESTRICTED option
+?(eval):cd:1: restricted
+?(eval):2: PATH: restricted
+?(eval):3: /bin/ls: restricted
+?(eval):hash:4: restricted: /bin/ls
+?(eval):5: writing redirection not allowed in restricted mode
+?(eval):exec:6: ls: restricted
+?(eval):unsetopt:7: can't change option: restricted
+
+  fn() {
+    print =ls ={ls,}
+    local foo='=ls'
+    print ${~foo}
+  }
+  setopt shfileexpansion
+  fn
+  unsetopt shfileexpansion
+  fn
+0q:SH_FILE_EXPANSION option
+>$lspath =ls =
+>=ls
+>$lspath $lspath =
+>$lspath
+
+  testpat() {
+    if [[ $1 = ${~2} ]]; then print $1 $2 yes; else print $1 $2 no; fi
+  }
+  print option on
+  setopt shglob
+  repeat 2; do
+    for str in 'a(b|c)' ab; do
+      testpat $str 'a(b|c)'
+    done
+    for str in 'a<1-10>' a9; do
+      testpat $str 'a<1-10>'
+    done
+    [[ ! -o shglob ]] && break
+    print option off
+    unsetopt shglob
+  done
+0:SH_GLOB option
+>option on
+>a(b|c) a(b|c) yes
+>ab a(b|c) no
+>a<1-10> a<1-10> yes
+>a9 a<1-10> no
+>option off
+>a(b|c) a(b|c) no
+>ab a(b|c) yes
+>a<1-10> a<1-10> no
+>a9 a<1-10> yes
+
+  print this is bar >bar
+  fn() {
+    local NULLCMD=cat READNULLCMD=cat
+    echo hello | >foo
+    cat foo
+    <bar
+  }
+  setopt shnullcmd
+  print option set
+  fn
+  unsetopt shnullcmd
+  print option unset
+  fn
+  rm -f foo bar
+0:SH_NULLCMD option
+>option set
+>option unset
+>hello
+>this is bar
+
+  fn() { 
+    eval 'for f in foo bar; print $f'
+    eval 'for f (word1 word2) print $f'
+    eval 'repeat 3 print nonsense'
+  }
+  unsetopt shortloops
+  print option unset
+  fn
+  setopt shortloops
+  print option set
+  fn
+0:SHORT_LOOPS option
+>option unset
+>option set
+>foo
+>bar
+>word1
+>word2
+>nonsense
+>nonsense
+>nonsense
+?(eval):1: parse error near `print'
+?(eval):1: parse error near `print'
+?(eval):1: parse error near `print'
+
+  fn() { print -l $*; }
+  setopt shwordsplit
+  print option set
+  repeat 2; do
+    foo='two words'
+    fn $foo
+    fn "${=foo}"
+    [[ ! -o shwordsplit ]] && break
+    unsetopt shwordsplit
+    print option unset
+  done
+0:SH_WORD_SPLIT option
+>option set
+>two
+>words
+>two
+>words
+>option unset
+>two words
+>two
+>words
+
+  fn() { unset foo; print $foo; }
+  setopt nounset
+  print option unset unset by setting nounset
+  eval fn
+  print option unset reset
+  setopt unset
+  fn
+0:UNSET option
+>option unset unset by setting nounset
+>option unset reset
+>
+?fn: foo: parameter not set
+
+# This really just tests if XTRACE is egregiously broken.
+# To test it properly would need a full set of its own.
+  fn() { print message; }
+  setopt xtrace
+  fn
+  unsetopt xtrace
+  fn
+0:XTRACE option
+>message
+>message
+?+(eval):3> fn
+?+fn:0> print message
+?+(eval):4> unsetopt xtrace