about summary refs log tree commit diff
path: root/Test
diff options
context:
space:
mode:
authorPaul Ackersviller <packersv@users.sourceforge.net>2007-06-25 03:11:44 +0000
committerPaul Ackersviller <packersv@users.sourceforge.net>2007-06-25 03:11:44 +0000
commitf2f3b86a5f15500dfee707d27eee9784a1626e4d (patch)
treed58c84a358497843dbdf54088e4e441bbf9447e1 /Test
parent3fb7cb46276374c248d24802e04d0947743d2d8d (diff)
downloadzsh-f2f3b86a5f15500dfee707d27eee9784a1626e4d.tar.gz
zsh-f2f3b86a5f15500dfee707d27eee9784a1626e4d.tar.xz
zsh-f2f3b86a5f15500dfee707d27eee9784a1626e4d.zip
Merge of 21862/21863/21870: GLOB_SUBST shouldn't swallow up backslashes in
parameter substitutions that don't match anything.
Diffstat (limited to 'Test')
-rw-r--r--Test/D04parameter.ztst14
-rwxr-xr-xTest/ztst.zsh184
2 files changed, 160 insertions, 38 deletions
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 3ad19368d..6abba0ab3 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -196,6 +196,20 @@
 >* boringfile evenmoreboringfile boringfile evenmoreboringfile
 >boringfile evenmoreboringfile
 
+# The following tests a bug where globsubst didn't preserve
+# backslashes when printing out the original string.
+  str1='\\*\\'
+  (
+  setopt globsubst nonomatch
+  [[ \\\\ = $str1 ]] && print -r '\\ matched by' $str1
+  [[ \\foo\\ = $str1 ]] && print -r '\\foo matched by' $str1
+  [[ a\\b\\ = $str1 ]] || print -r 'a\\b not matched by' $str1
+  )
+0:globsubst with backslashes
+>\\ matched by \\*\\
+>\\foo matched by \\*\\
+>a\\b not matched by \\*\\
+
   print -l "${$(print one word)}" "${=$(print two words)}"
 0:splitting of $(...) inside ${...}
 >one word
diff --git a/Test/ztst.zsh b/Test/ztst.zsh
index fe996832c..c0fbc179f 100755
--- a/Test/ztst.zsh
+++ b/Test/ztst.zsh
@@ -22,9 +22,17 @@
 # still not be good enough.  Maybe we should trick it somehow.
 emulate -R zsh
 
+# Ensure the locale does not screw up sorting.  Don't supply a locale
+# unless there's one set, to minimise problems.
+[[ -n $LC_ALL ]] && LC_ALL=C
+[[ -n $LC_COLLATE ]] && LC_COLLATE=C
+[[ -n $LANG ]] && LANG=C
+
 # Set the module load path to correspond to this build of zsh.
 # This Modules directory should have been created by "make check".
 [[ -d Modules/zsh ]] && module_path=( $PWD/Modules )
+# Allow this to be passed down.
+export MODULE_PATH
 
 # We need to be able to save and restore the options used in the test.
 # We use the $options variable of the parameter module for this.
@@ -47,12 +55,48 @@ ZTST_mainopts=(${(kv)options})
 ZTST_testdir=$PWD
 ZTST_testname=$1
 
-# The source directory is not necessarily the current directory
-ZTST_srcdir=${0%/*}
+integer ZTST_testfailed
+
+# This is POSIX nonsense.  Because of the vague feeling someone, somewhere
+# may one day need to examine the arguments of "tail" using a standard
+# option parser, every Unix user in the world is expected to switch
+# to using "tail -n NUM" instead of "tail -NUM".  Older versions of
+# tail don't support this.
+tail() {
+  emulate -L zsh
+
+  if [[ -z $TAIL_SUPPORTS_MINUS_N ]]; then
+    local test
+    test=$(echo "foo\nbar" | command tail -n 1 2>/dev/null)
+    if [[ $test = bar ]]; then
+      TAIL_SUPPORTS_MINUS_N=1
+    else
+      TAIL_SUPPORTS_MINUS_N=0
+    fi
+  fi
+
+  integer argi=${argv[(i)-<->]}
+
+  if [[ $argi -le $# && $TAIL_SUPPORTS_MINUS_N = 1 ]]; then
+    argv[$argi]=(-n ${argv[$argi][2,-1]})
+  fi
+
+  command tail "$argv[@]"
+}
+
+# The source directory is not necessarily the current directory,
+# but if $0 doesn't contain a `/' assume it is.
+if [[ $0 = */* ]]; then
+  ZTST_srcdir=${0%/*}
+else
+  ZTST_srcdir=$PWD
+fi
 [[ $ZTST_srcdir = /* ]] || ZTST_srcdir="$ZTST_testdir/$ZTST_srcdir"
 
 # Set the function autoload paths to correspond to this build of zsh.
-fpath=( $ZTST_srcdir/../(Completion|Functions)/*~*/CVS(/) )
+fpath=( $ZTST_srcdir/../Functions/*~*/CVS(/)
+        $ZTST_srcdir/../Completion
+        $ZTST_srcdir/../Completion/*/*~*/CVS(/) )
 
 : ${TMPPREFIX:=/tmp/zsh}
 # Temporary files for redirection inside tests.
@@ -66,14 +110,15 @@ ZTST_terr=${TMPPREFIX}.ztst.terr.$$
 
 ZTST_cleanup() {
   cd $ZTST_testdir
-  rm -rf $ZTST_testdir/dummy.tmp $ZTST_testdir/*.tmp ${TMPPREFIX}.ztst*$$
+  rm -rf $ZTST_testdir/dummy.tmp $ZTST_testdir/*.tmp(N) \
+    ${TMPPREFIX}.ztst*$$(N)
 }
 
 # This cleanup always gets performed, even if we abort.  Later,
 # we should try and arrange that any test-specific cleanup
 # always gets called as well.
-trap - 'print cleaning up...
-ZTST_cleanup' INT QUIT TERM
+##trap 'print cleaning up...
+##ZTST_cleanup' INT QUIT TERM
 # Make sure it's clean now.
 rm -rf dummy.tmp *.tmp
 
@@ -85,20 +130,31 @@ ZTST_testfailed() {
     print -r "Was testing: $ZTST_message"
   fi
   print -r "$ZTST_testname: test failed."
-  ZTST_cleanup
-  exit 1
+  if [[ -n $ZTST_failmsg ]]; then
+    print -r "The following may (or may not) help identifying the cause:
+$ZTST_failmsg"
+  fi
+  ZTST_testfailed=1
+  return 1
 }
 
 # Print messages if $ZTST_verbose is non-empty
 ZTST_verbose() {
   local lev=$1
   shift
-  [[ -n $ZTST_verbose && $ZTST_verbose -ge $lev ]] && print -- $* >&8
+  [[ -n $ZTST_verbose && $ZTST_verbose -ge $lev ]] && print -r -- $* >&8
+}
+ZTST_hashmark() {
+  [[ ZTST_verbose -le 0 && -t 8 ]] && print -nu8 ${(pl:SECONDS::\#::\#\r:)}
+  (( SECONDS > COLUMNS+1 && (SECONDS -= COLUMNS) ))
 }
 
-[[ ! -r $ZTST_testname ]] && ZTST_testfailed "can't read test file."
+if [[ ! -r $ZTST_testname ]]; then
+  ZTST_testfailed "can't read test file."
+  exit 1
+fi
 
-[[ -n $ZTST_verbose && $ZTST_verbose -ge 0 ]] && exec 8>&1
+exec 8>&1
 exec 9<$ZTST_testname
 
 # The current line read from the test file.
@@ -118,15 +174,18 @@ ZTST_getline() {
 
 # Get the name of the section.  It may already have been read into
 # $curline, or we may have to skip some initial comments to find it.
+# If argument present, it's OK to skip the reset of the current section,
+# so no error if we find garbage.
 ZTST_getsect() {
   local match mbegin mend
 
   while [[ $ZTST_curline != '%'(#b)([[:alnum:]]##)* ]]; do
     ZTST_getline || return 1
     [[ $ZTST_curline = [[:blank:]]# ]] && continue
-    if [[ $ZTST_curline != '%'[[:alnum:]]##* ]]; then
+    if [[ $# -eq 0 && $ZTST_curline != '%'[[:alnum:]]##* ]]; then
       ZTST_testfailed "bad line found before or after section:
 $ZTST_curline"
+      exit 1
     fi
   done
   # have the next line ready waiting
@@ -169,13 +228,14 @@ ${ZTST_curline[2,-1]}"
 $ZTST_redir"
 
 case $char in
-  '<') fn=$ZTST_in
+  ('<') fn=$ZTST_in
        ;;
-  '>') fn=$ZTST_out
+  ('>') fn=$ZTST_out
        ;;
-  '?') fn=$ZTST_err
+  ('?') fn=$ZTST_err
        ;;
-   *)  ZTST_testfailed "bad redir operator: $char"
+   (*)  ZTST_testfailed "bad redir operator: $char"
+       return 1
        ;;
 esac
 if [[ $ZTST_flags = *q* ]]; then
@@ -183,6 +243,8 @@ if [[ $ZTST_flags = *q* ]]; then
 else
   print -r -- "$ZTST_redir" >>$fn
 fi
+
+return 0
 }
 
 # Execute an indented chunk.  Redirections will already have
@@ -191,9 +253,10 @@ ZTST_execchunk() {
   options=($ZTST_testopts)
   eval "$ZTST_code"
   ZTST_status=$?
+  # careful... ksh_arrays may be in effect.
+  ZTST_testopts=(${(kv)options[*]})
+  options=(${ZTST_mainopts[*]})
   ZTST_verbose 2 "ZTST_execchunk: status $ZTST_status"
-  ZTST_testopts=(${(kv)options})
-  options=($ZTST_mainopts)
   return $ZTST_status
 }
 
@@ -202,12 +265,27 @@ ZTST_execchunk() {
 ZTST_prepclean() {
   # Execute indented code chunks.
   while ZTST_getchunk; do
-    ZTST_execchunk >/dev/null || [[ -n $1 ]] ||
-    ZTST_testfailed "non-zero status from preparation code:
-$ZTST_code"
+    ZTST_execchunk >/dev/null || [[ -n $1 ]] || {
+      [[ -n "$ZTST_unimplemented" ]] ||
+      ZTST_testfailed "non-zero status from preparation code:
+$ZTST_code" && return 0
+    }
   done
 }
 
+# diff wrapper
+ZTST_diff() {
+  local diff_out diff_ret
+
+  diff_out=$(diff "$@")
+  diff_ret="$?"
+  if [[ "$diff_ret" != "0" ]]; then
+    print -r "$diff_out"
+  fi
+
+  return "$diff_ret"
+}
+    
 ZTST_test() {
   local last match mbegin mend found
 
@@ -215,6 +293,7 @@ ZTST_test() {
     rm -f $ZTST_in $ZTST_out $ZTST_err
     touch $ZTST_in $ZTST_out $ZTST_err
     ZTST_message=''
+    ZTST_failmsg=''
     found=0
 
     ZTST_verbose 2 "ZTST_test: looking for new test"
@@ -223,14 +302,14 @@ ZTST_test() {
       ZTST_verbose 2 "ZTST_test: examining line:
 $ZTST_curline"
       case $ZTST_curline in
-	%*) if [[ $found = 0 ]]; then
+	(%*) if [[ $found = 0 ]]; then
 	      break 2
 	    else
 	      last=1
 	      break
 	    fi
 	    ;;
-	[[:space:]]#)
+	([[:space:]]#)
 	    if [[ $found = 0 ]]; then
 	      ZTST_getline || break 2
 	      continue
@@ -238,7 +317,7 @@ $ZTST_curline"
 	      break
 	    fi
 	    ;;
-	[[:space:]]##[^[:space:]]*) ZTST_getchunk
+	([[:space:]]##[^[:space:]]*) ZTST_getchunk
 	  if [[ $ZTST_curline == (#b)([-0-9]##)([[:alpha:]]#)(:*)# ]]; then
 	    ZTST_xstatus=$match[1]
 	    ZTST_flags=$match[2]
@@ -246,29 +325,38 @@ $ZTST_curline"
 	  else
 	    ZTST_testfailed "expecting test status at:
 $ZTST_curline"
+	    return 1
 	  fi
 	  ZTST_getline
 	  found=1
 	  ;;
-	'<'*) ZTST_getredir
+	('<'*) ZTST_getredir || return 1
 	  found=1
 	  ;;
-	'>'*) ZTST_getredir
+	('>'*) ZTST_getredir || return 1
 	  found=1
 	  ;;
-	'?'*) ZTST_getredir
+	('?'*) ZTST_getredir || return 1
 	  found=1
 	  ;;
-	*) ZTST_testfailed "bad line in test block:
+	('F:'*) ZTST_failmsg="${ZTST_failmsg:+${ZTST_failmsg}
+}  ${ZTST_curline[3,-1]}"
+	  ZTST_getline
+	  found=1
+          ;;
+	(*) ZTST_testfailed "bad line in test block:
 $ZTST_curline"
+	  return 1
           ;;
       esac
     done
 
     # If we found some code to execute...
     if [[ -n $ZTST_code ]]; then
+      ZTST_hashmark
       ZTST_verbose 1 "Running test: $ZTST_message"
       ZTST_verbose 2 "ZTST_test: expecting status: $ZTST_xstatus"
+      ZTST_verbose 2 "Input: $ZTST_in, output: $ZTST_out, error: $ZTST_terr"
 
       ZTST_execchunk <$ZTST_in >$ZTST_tout 2>$ZTST_terr
 
@@ -278,6 +366,7 @@ $ZTST_curline"
 $ZTST_code${$(<$ZTST_terr):+
 Error output:
 $(<$ZTST_terr)}"
+	return 1
       fi
 
       ZTST_verbose 2 "ZTST_test: test produced standard output:
@@ -286,15 +375,17 @@ ZTST_test: and standard error:
 $(<$ZTST_terr)"
 
       # Now check output and error.
-      if [[ $ZTST_flags != *d* ]] && ! diff -c $ZTST_out $ZTST_tout; then
+      if [[ $ZTST_flags != *d* ]] && ! ZTST_diff -c $ZTST_out $ZTST_tout; then
 	ZTST_testfailed "output differs from expected as shown above for:
 $ZTST_code${$(<$ZTST_terr):+
 Error output:
 $(<$ZTST_terr)}"
+	return 1
       fi
-      if [[ $ZTST_flags != *D* ]] && ! diff -c $ZTST_err $ZTST_terr; then
+      if [[ $ZTST_flags != *D* ]] && ! ZTST_diff -c $ZTST_err $ZTST_terr; then
 	ZTST_testfailed "error output differs from expected as shown above for:
 $ZTST_code"
+	return 1
       fi
     fi
     ZTST_verbose 1 "Test successful."
@@ -312,35 +403,52 @@ $ZTST_code"
 typeset -A ZTST_sects
 ZTST_sects=(prep 0 test 0 clean 0)
 
+print "$ZTST_testname: starting."
+
 # Now go through all the different sections until the end.
-while ZTST_getsect; do
+# prep section may set ZTST_unimplemented, in this case the actual
+# tests will be skipped
+ZTST_skipok=
+ZTST_unimplemented=
+while [[ -z "$ZTST_unimplemented" ]] && ZTST_getsect $ZTST_skipok; do
   case $ZTST_cursect in
-    prep) if (( ${ZTST_sects[prep]} + ${ZTST_sects[test]} + \
+    (prep) if (( ${ZTST_sects[prep]} + ${ZTST_sects[test]} + \
 	        ${ZTST_sects[clean]} )); then
 	    ZTST_testfailed "\`prep' section must come first"
+            exit 1
 	  fi
 	  ZTST_prepclean
 	  ZTST_sects[prep]=1
 	  ;;
-    test)
+    (test)
 	  if (( ${ZTST_sects[test]} + ${ZTST_sects[clean]} )); then
 	    ZTST_testfailed "bad placement of \`test' section"
+	    exit 1
 	  fi
+	  # careful here: we can't execute ZTST_test before || or &&
+	  # because that affects the behaviour of traps in the tests.
 	  ZTST_test
+	  (( $? )) && ZTST_skipok=1
 	  ZTST_sects[test]=1
 	  ;;
-    clean)
+    (clean)
 	   if (( ${ZTST_sects[test]} == 0 || ${ZTST_sects[clean]} )); then
 	     ZTST_testfailed "bad use of \`clean' section"
+	   else
+	     ZTST_prepclean 1
+	     ZTST_sects[clean]=1
 	   fi
-	   ZTST_prepclean 1
-	   ZTST_sects[clean]=1
+	   ZTST_skipok=
 	   ;;
     *) ZTST_testfailed "bad section name: $ZTST_cursect"
        ;;
   esac
 done
 
-print "$ZTST_testname: all tests successful."
+if [[ -n "$ZTST_unimplemented" ]]; then
+  print "$ZTST_testname: skipped ($ZTST_unimplemented)"
+elif (( ! $ZTST_testfailed )); then
+  print "$ZTST_testname: all tests successful."
+fi
 ZTST_cleanup
-exit 0
+exit $(( ZTST_testfailed ))