bug-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: sanity.sh find_tool() revisions


From: Mark D. Baushke
Subject: Re: sanity.sh find_tool() revisions
Date: Fri, 05 Nov 2004 08:49:59 -0800

Hi Folks,

Problem statement:

    sanity.sh uses find_tool to search for a replacement of a tool that
    may not have passed at least one sanity test. Unfortunately, do to
    the way that it is written, it will only find the first g<name> or
    <name> in the user's PATH or some other common directories that may
    have tools. So, even though there may be multiple versions of 'id'
    or 'expr' in your path, it will not necessarily find one that
    satisfies its request.

    For example, on Solaris, /usr/bin/id does not accept the -u -n
    switches, but the user may have a /usr/local/bin/id that does the
    right thing. The user may also have the id-utils package installed,
    so looking for 'id' as 'gid' is just the wrong thing to do.

Suggested solution:

    Modify the find_tool function to first find the set of executable
    programs or scripts found in the PATH (plus some other added
    directories that may or may not exist) and run a series of tests to
    ensure that the tool found functions as expected. If none of the
    tools are found, print out an error message and terminate.

    If the only tool that is found is one that MIGHT produce spurious
    results, write a notice of this possibility to stderr and the
    check.log file as a warning to the user.

    The check.log file will also be updated to include the tools being
    used and how each of the candidate tools may have perfomed during
    testing.

Suggested API & find_tool implementation:

# Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
# Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
find_tool ()
{
  default_TOOL=$1
  echo find_tool: ${1+"$@"} >>$LOGFILE
  cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
  if test -z "$tooltests"; then tooltests=version_test; fi
  clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
  TOOL=""
  for trytool in $clist ; do
    pass=:
    for tooltest in $tooltests; do
      result=`eval $tooltest $trytool`
      rc=$?
      echo "Running $tooltest $trytool" >>$LOGFILE
      if test -n "$result"; then
        echo "$result" >>$LOGFILE
      fi
      if test "$rc" = "0"; then
        echo "PASS: $tooltest $trytool" >>$LOGFILE
      elif test "$rc" = "77"; then
        echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
        TOOL=$trytool
        pass=false
      else
        set_bad_tool $trytool
        echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
        pass=false
      fi
    done
    if $pass; then
      echo $trytool
      return 0
    fi
  done
  # Make surethe default tool is just the first command name
  for default_TOOL in `IFS=:; echo $default_TOOL`; do break; done
  if test -n "$TOOL"; then
    echo "Notice: The default version of \`$default_TOOL' is defective." 
>>$LOGFILE
    echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
    echo "Notice: The default version of \`$default_TOOL' is defective." >&2
    echo "using \`$TOOL' and hoping for the best." >&2
    echo $TOOL
  else
    echo $default_TOOL
  fi
}  

The suggested patch to sanity.sh is included after my .signature.

Do folks think this is a worthwhile improvement?

        Thanks,
        -- Mark

Index: sanity.sh
===================================================================
RCS file: /cvs/ccvs/src/sanity.sh,v
retrieving revision 1.1014
diff -u -p -r1.1014 sanity.sh
--- sanity.sh   4 Nov 2004 20:05:43 -0000       1.1014
+++ sanity.sh   5 Nov 2004 16:16:59 -0000
@@ -709,41 +709,89 @@ is_bad_tool ()
    case ":$badtools:" in *:$1:*) return 0 ;; *) return 1 ; esac
 }
 
+version_test ()
+{
+  vercmd=$1
+  if RES=`$vercmd --version </dev/null 2>/dev/null`; then
+    if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
+      echo "$RES"
+      return 0
+    else
+      echo "$RES"
+      echo "The command \`$vercmd' does not support the --version option."
+    fi
+  fi
+  return 1
+}
+
+# Try to find a tool that satisfies all of the tests.
+# Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
+# Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
 find_tool ()
 {
+  default_TOOL=$1
+  echo find_tool: ${1+"$@"} >>$LOGFILE
+  cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
+  if test -z "$tooltests"; then tooltests=version_test; fi
+  clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
   TOOL=""
-  for path in `IFS=:; echo $SEARCHPATH`; do
-    if is_bad_tool $path/g$1 ; then continue; fi
-    if test -f $path/g$1 && test -r $path/g$1 &&
-        RES=`$path/g$1 --version </dev/null 2>/dev/null`; then
-      if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
-        TOOL=$path/g$1
-        break
+  for trytool in $clist ; do
+    pass=:
+    for tooltest in $tooltests; do
+      result=`eval $tooltest $trytool`
+      rc=$?
+      echo "Running $tooltest $trytool" >>$LOGFILE
+      if test -n "$result"; then
+       echo "$result" >>$LOGFILE
       fi
-    fi
-    if is_bad_tool $path/$1 ; then continue; fi
-    if test -f $path/$1 && test -r $path/$1 &&
-        RES=`$path/$1 --version </dev/null 2>/dev/null`; then
-      if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
-        TOOL=$path/$1
-        break
+      if test "$rc" = "0"; then
+        echo "PASS: $tooltest $trytool" >>$LOGFILE
+      elif test "$rc" = "77"; then
+        echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
+        TOOL=$trytool
+       pass=false
+      else
+        set_bad_tool $trytool
+        echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
+       pass=false
       fi
+    done
+    if $pass; then
+      echo $trytool
+      return 0
     fi
   done
-  if test -z "$TOOL"; then
-    :
+  # Make surethe default tool is just the first command name
+  for default_TOOL in `IFS=:; echo $default_TOOL`; do break; done
+  if test -n "$TOOL"; then
+    echo "Notice: The default version of \`$default_TOOL' is defective." 
>>$LOGFILE
+    echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
+    echo "Notice: The default version of \`$default_TOOL' is defective." >&2
+    echo "using \`$TOOL' and hoping for the best." >&2
+    echo $TOOL
   else
-    echo "Notice: The default version of \`$1' is defective, using" >&2
-    echo "\`$TOOL' instead." >&2
+    echo $default_TOOL
   fi
-  echo "$TOOL"
 }  
 
+id_tool_test ()
+{
+  id=$1
+  if $id -u >/dev/null 2>&1 && $id -un >/dev/null 2>&1; then
+    return 0
+  else
+    echo "Running these tests requires an \`id' program that understands the"
+    echo "-u and -n flags.  Make sure that such an id (GNU, or many but not"
+    echo "all vendor-supplied versions) is in your path."
+    return 1
+  fi
+}
+
+ID=`find_tool id version_test id_tool_test`
+echo "Using ID=$ID" >>$LOGFILE
+
 # You can't run CVS as root; print a nice error message here instead
 # of somewhere later, after making a mess.
-#
-# FIXME - find_tool() finds the 'gid' from GNU id-utils if I pull 'id' out of
-# my path.
 for pass in false :; do
   case "`$ID -u 2>/dev/null`" in
     "0")
@@ -751,18 +799,6 @@ for pass in false :; do
       exit 1
       ;;
 
-    "")
-      if $pass; then :; else
-       ID=`find_tool id`
-      fi
-      if $pass || test -z "$ID" ; then
-       echo "Running these tests requires an \`id' program that understands 
the" >&2
-       echo "-u and -n flags.  Make sure that such an id (GNU, or many but 
not" >&2
-       echo "all vendor-supplied versions) is in your path." >&2
-       exit 1
-      fi
-      ;;
-
     *)
       break
       ;;
@@ -770,63 +806,70 @@ for pass in false :; do
 done
 
 # Cause NextStep 3.3 users to lose in a more graceful fashion.
-if $EXPR 'abc
+expr_tooltest1 ()
+{
+expr=$1
+if $expr 'abc
 def' : 'abc
 def' >/dev/null; then
-  : good, it works
+  # good, it works
+  return 0
 else
-  EXPR=`find_tool expr`
-  if test -z "$EXPR" ; then
-    echo 'Running these tests requires an "expr" program that can handle' >&2
-    echo 'multi-line patterns.  Make sure that such an expr (GNU, or many but' 
>&2
-    echo 'not all vendor-supplied versions) is in your path.' >&2
-    exit 1
-  fi
+  echo 'Running these tests requires an "expr" program that can handle'
+  echo 'multi-line patterns.  Make sure that such an expr (GNU, or many but'
+  echo 'not all vendor-supplied versions) is in your path.'
+  return 1
 fi
+}
 
 # Warn SunOS, SysVr3.2, etc., users that they may be partially losing
 # if we can't find a GNU expr to ease their troubles...
-if $EXPR 'a
+expr_tooltest2 ()
+{
+expr=$1
+if $expr 'a
 b' : 'a
 c' >/dev/null; then
-  EXPR=`find_tool expr`
-  if test -z "$EXPR" ; then
-    echo 'Warning: you are using a version of expr that does not correctly'
-    echo 'match multi-line patterns.  Some tests may spuriously pass or fail.'
-    echo 'You may wish to make sure GNU expr is in your path.'
-    EXPR=expr
-  fi
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match multi-line patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
 else
-  : good, it works
+  return 0
 fi
+}
 
-# More SunOS lossage...
+expr_create_bar ()
+{
 echo 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >${TESTDIR}/foo
 cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
 cat ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar >${TESTDIR}/foo
 cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
-if $EXPR "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
+rm -f ${TESTDIR}/foo
+}
+
+expr_tooltest3 ()
+{
+expr=$1
+# More SunOS lossage...
+test ! -f ${TESTDIR}/bar && expr_create_bar
+if $expr "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
   : good, it works
 else
-  EXPR=`find_tool expr`
-  if test -z "$EXPR" ; then
-    echo 'Warning: you are using a version of expr that does not correctly'
-    echo 'match large patterns.  Some tests may spuriously pass or fail.'
-    echo 'You may wish to make sure GNU expr is in your path.'
-    EXPR=expr
-  fi
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
 fi
 if $EXPR "`cat ${TESTDIR}/bar`x" : "`cat ${TESTDIR}/bar`y" >/dev/null; then
-  EXPR=`find_tool expr`
-  if test -z "$EXPR" ; then
-    echo 'Warning: you are using a version of expr that does not correctly'
-    echo 'match large patterns.  Some tests may spuriously pass or fail.'
-    echo 'You may wish to make sure GNU expr is in your path.'
-    EXPR=expr
-  fi
-else
-  : good, it works
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 1
 fi
+# good, it works
+return 0
+}
 
 # That we should have to do this is total bogosity, but GNU expr
 # version 1.9.4-1.12 uses the emacs definition of "$" instead of the unix
@@ -834,10 +877,18 @@ fi
 # next release of GNU expr after 1.12 (but we still have to cater to the old
 # ones for some time because they are in many linux distributions).
 ENDANCHOR="$"
-if $EXPR 'abc
+expr_set_ENDANCHOR ()
+{
+expr=$1
+ENDANCHOR="$"
+if $expr 'abc
 def' : 'abc$' >/dev/null; then
   ENDANCHOR='\'\'
+   echo "Notice: An ENDANCHOR of dollar does not work."
+   echo "Using a workaround for GNU expr versions 1.9.4 thru 1.12"
 fi
+return 0
+}
 
 # Work around another GNU expr (version 1.10-1.12) bug/incompatibility.
 # "." doesn't appear to match a newline (it does with SunOS 4.1.3 expr).
@@ -848,28 +899,53 @@ fi
 # next release of GNU expr after 1.12 (but we still have to cater to the old
 # ones for some time because they are in many linux distributions).
 DOTSTAR='.*'
-if $EXPR 'abc
+expr_set_DOTSTAR ()
+{
+expr=$1
+DOTSTAR='.*'
+if $expr 'abc
 def' : "a${DOTSTAR}f" >/dev/null; then
   : good, it works
 else
   DOTSTAR='\(.\|
 \)*'
+  echo "Notice: DOTSTAR changed from sane \`.*' value to \`$DOTSTAR\`"
+  echo "to workaround GNU expr version 1.10 thru 1.12 bug where \`.'"
+  echo "does not match a newline."
 fi
+return 0
+}
 
 # Now that we have DOTSTAR, make sure it works with big matches
-if $EXPR "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; 
then
-  : good, it works
+expr_tooltest_DOTSTAR ()
+{
+expr=$1
+test ! -f ${TESTDIR}/bar && expr_create_bar
+if $expr "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; 
then
+  # good, it works
+  return 0
 else
-  EXPR=`find_tool expr`
-  if test -z "$EXPR" ; then
-    echo 'Warning: you are using a version of expr that does not correctly'
-    echo 'match large patterns.  Some tests may spuriously pass or fail.'
-    echo 'You may wish to make sure GNU expr is in your path.'
-    EXPR=expr
-  fi
+  echo 'Warning: you are using a version of expr that does not correctly'
+  echo 'match large patterns.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU expr is in your path.'
+  return 77
 fi
+}
+
+EXPR=`find_tool ${EXPR}:gexpr \
+  version_test expr_tooltest1 expr_tooltest2 expr_tooltest3 \
+expr_set_ENDANCHOR expr_set_DOTSTAR expr_tooltest_DOTSTAR`
+
+# Set the ENDANCHOR and DOTSTAR for the chosen expr version.
+expr_set_ENDANCHOR ${EXPR} >/dev/null
+expr_tooltest_DOTSTAR ${EXPR} >/dev/null
+
+echo "Using EXPR=$EXPR" >>$LOGFILE
+echo "Using ENDANCHOR=$ENDANCHOR" >>$LOGFILE
+echo "Using DOTSTAR=$DOTSTAR" >>$LOGFILE
 
-rm -f ${TESTDIR}/foo ${TESTDIR}/bar
+# Cleanup
+rm -f ${TESTDIR}/bar
 
 # Work around yet another GNU expr (version 1.10) bug/incompatibility.
 # "+" is a special character, yet for unix expr (e.g. SunOS 4.1.3)
@@ -904,47 +980,88 @@ else
 fi
 
 # now make sure that tr works on NULs
-if $EXPR `echo "123" | ${TR} '2' '\0'` : "123" >/dev/null 2>&1; then
-  TR=`find_tool tr`
-  if test -z "$TR" ; then
-    echo 'Warning: you are using a version of tr which does not correctly'
-    echo 'handle NUL bytes.  Some tests may spuriously pass or fail.'
-    echo 'You may wish to make sure GNU tr is in your path.'
-    TR=tr
-  fi
-else
-  : good, it works
+tr_tooltest1 ()
+{
+tr=$1
+if $EXPR `echo "123" | $tr '2' '\0'` : "123" >/dev/null 2>&1; then
+  echo 'Warning: you are using a version of tr which does not correctly'
+  echo 'handle NUL bytes.  Some tests may spuriously pass or fail.'
+  echo 'You may wish to make sure GNU tr is in your path.'
+  return 77
 fi
+# good, it works
+return 0
+}
 
+TR=`find_tool ${TR}:gtr version_test tr_tooltest1`
+echo "Using TR=$TR" >>$LOGFILE
 
 # MacOS X (10.2.8) has a /bin/ls that does not work correctly in that
 # it will return true even if the wildcard argument does not match any
 # files.
+ls_tooltest ()
+{
+ls=$1
+# Force cleanup
 if test -d $TESTDIR/ls-test; then
     chmod -R a+wx $TESTDIR/ls-test
     rm -rf $TESTDIR/ls-test
 fi
-LS=`Which ls`
-if ${LS} $TESTDIR/ls-test >/dev/null 2>&1; then
-    echo "Notice: The default version of \`ls' in \`${LS}' is defective."
-    for tryls in `Which -a ls` ; do
-        if [ ${tryls} = ${LS} ]; then continue; fi
-       if ${tryls} $TESTDIR/ls-test >/dev/null 2>&1; then
-           echo "Attempt to use \`${tryls}' also failed. It is defective."
-        else
-            LS=${tryls}
-           break
-       fi
-    done
-    if ${LS} $TESTDIR/ls-test >/dev/null 2>&1; then
-        echo 'Warning: you are using a version of ls which does not correctly'
-        echo 'return false for files that do not exist. Some tests may'
-        echo 'spuriously pass or fail.'
-        echo 'You may wish to put a an ls from GNU coreutils into your path.'
-    else
-        echo "Using \`${LS}' as a replacement version of \`ls'."
-    fi
+if $ls $TESTDIR/ls-test >/dev/null 2>&1; then
+  echo "Notice: \`$ls' is defective."
+  echo 'This is a version of ls which does not correctly'
+  echo 'return false for files that do not exist. Some tests may'
+  echo 'spuriously pass or fail.'
+  echo 'You may wish to put a an ls from GNU coreutils into your path.'
+  return 77
+else
+  return 0
+fi
+}
+LS=`find_tool ls:gls version_test ls_tooltest`
+echo "Using LS=$LS" >>$LOGFILE
+
+# Awk testing
+
+awk_tooltest1 ()
+{
+awk=$1
+$awk 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
+if $EXPR "`cat abc`" : \
+'one
+two
+three
+four
+five
+six'; then
+  rm abc
+  return 0
+else
+  rm abc
+  echo "Notice: awk BEGIN clause or printf is not be working properly."
+  return 1
+fi
+}
+
+# Format item %c check
+awk_tooltest2 ()
+{
+awk=$1
+$awk 'BEGIN { printf "%c%c%c", 2, 3, 4 }' </dev/null \
+  | ${TR} '\002\003\004' '123' >abc
+if $EXPR "`cat abc`" : "123" ; then
+  : good, found it
+else
+  echo "Notice: awk format %c string may not be working properly."
+  rm abc
+  return 77
 fi
+rm abc
+return 0
+}
+
+AWK=`find_tool gawk:nawk:awk version_test awk_tooltest1 awk_tooltest2`
+echo "Using AWK=$AWK" >>$LOGFILE
 
 
 ###




reply via email to

[Prev in Thread] Current Thread [Next in Thread]