PageRenderTime 122ms CodeModel.GetById 39ms app.highlight 48ms RepoModel.GetById 0ms app.codeStats 4ms

/contrib/cvs/src/sanity.sh

https://bitbucket.org/freebsd/freebsd-head/
Shell | 15696 lines | 12386 code | 1394 blank | 1916 comment | 457 complexity | cceaf0e0b88c0126424fe2fefc488af9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#! /bin/sh
   2:
   3#	sanity.sh -- a growing testsuite for cvs.
   4#
   5# The copyright notice said: "Copyright (C) 1992, 1993 Cygnus Support"
   6# I'm not adding new copyright notices for new years as our recent 
   7# practice has been to include copying terms without copyright notices.
   8#
   9# This program is free software; you can redistribute it and/or modify
  10# it under the terms of the GNU General Public License as published by
  11# the Free Software Foundation; either version 2, or (at your option)
  12# any later version.
  13#
  14# This program is distributed in the hope that it will be useful,
  15# but WITHOUT ANY WARRANTY; without even the implied warranty of
  16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17# GNU General Public License for more details.
  18#
  19# Original Author: K. Richard Pixley
  20
  21# usage:
  22usage ()
  23{
  24    echo "Usage: `basename $0` --help"
  25    echo "Usage: `basename $0` [-eklrv] [-f FROM-TEST] [-h HOSTNAME] CVS-TO-TEST [TESTS-TO-RUN...]"
  26}
  27
  28exit_usage ()
  29{
  30    usage 1>&2
  31    exit 2
  32}
  33
  34exit_help ()
  35{
  36    usage
  37    echo
  38    echo "-H|--help     Display this text."
  39    echo "-e|--skipfail Treat tests that would otherwise be nonfatally skipped"
  40    echo "              for reasons like missing tools as failures, exiting"
  41    echo "              with an error message.  Also treat warnings as"
  42    echo "              failures."
  43    echo "-f FROM-TEST  Run TESTS-TO-RUN, skipping all tests in the list before"
  44    echo "              FROM-TEST."
  45    echo "-h HOSTNAME   Use :ext:HOSTNAME to run remote tests rather than"
  46    echo "              :fork:.  Implies --remote and assumes that \$TESTDIR"
  47    echo "              resolves to the same directory on both the client and"
  48    echo "              the server."
  49    echo "-k|--keep     Try to keep directories created by individual tests"
  50    echo "              around, exiting after the first test which supports"
  51    echo "              --keep."
  52    echo "-l|--link-root"
  53    echo "              Test CVS using a symlink to a real CVSROOT."
  54    echo "-r|--remote   Test remote instead of local cvs."
  55    echo "-v|--verbose  List test names as they are executed."
  56    echo
  57    echo "CVS-TO-TEST   The path to the CVS executable to be tested."
  58    echo "TESTS-TO-RUN  The names of the tests to run (defaults to all tests)."
  59    exit 2
  60}
  61
  62# See TODO list at end of file.
  63
  64# required to make this script work properly.
  65unset CVSREAD
  66
  67# This will cause malloc to run slower but should also catch some common errors
  68# when CVS is linked with glibc 2.x.
  69MALLOC_CHECK_=2; export MALLOC_CHECK_
  70
  71# We want to invoke a predictable set of i18n behaviors, not whatever
  72# the user running this script might have set.
  73# In particular:
  74#   'sort' and tabs and spaces (LC_COLLATE).
  75#   Messages from getopt (LC_MESSAGES) (in the future, CVS itself might 
  76#     also alter its messages based on LC_MESSAGES).
  77LANG=C
  78export LANG
  79LC_ALL=C
  80export LC_ALL
  81
  82
  83#
  84# Initialize the test counts.
  85#
  86passed=0
  87skipped=0
  88warnings=0
  89
  90
  91
  92#
  93# read our options
  94#
  95unset fromtest
  96unset remotehost
  97keep=false
  98linkroot=false
  99remote=false
 100skipfail=false
 101verbose=false
 102while getopts ef:h:Hklrv-: option ; do
 103    # convert the long opts to short opts
 104    if test x$option = x-;  then
 105	case "$OPTARG" in
 106	    [hH]|[hH][eE]|[hH][eE][lL]|[hH][eE][lL][pP])
 107		option=H;
 108		OPTARG=
 109		;;
 110	    [kK]|[kK][eE]|[kK][eE][eE]|[kK][eE][eE][pP])
 111		option=k;
 112		OPTARG=
 113		;;
 114	    l|li|lin|link|link-|link-r]|link-ro|link-roo|link-root)
 115		option=l;
 116		OPTARG=
 117		;;
 118	    [rR]|[rR][eE]|[rR][eE][mM]|[rR][eE][mM][oO]|[rR][eE][mM][oO][tT]|[rR][eE][mM][oO][tT][eE])
 119		option=k;
 120		OPTARG=
 121		;;
 122	    s|sk|ski|skip|skipf|skipfa|skipfai|skipfail)
 123		option=e
 124		OPTARG=
 125		;;
 126	    v|ve|ver|verb|verbo|verbos|verbose)
 127		option=v
 128		OPTARG=
 129		;;
 130	    *)
 131		option=\?
 132		OPTARG=
 133	esac
 134    fi
 135    case "$option" in
 136	e)
 137	    skipfail=:
 138	    ;;
 139	f)
 140	    fromtest="$OPTARG"
 141	    ;;
 142	h)
 143	    # Set a remotehost to run the remote tests on via :ext:
 144	    # Implies `-r' and assumes that $TESTDIR resolves to the same
 145	    # directory on the client and the server.
 146	    remotehost="$OPTARG"
 147	    remote=:
 148	    ;;
 149	H)
 150	    exit_help
 151	    ;;
 152	k)
 153	    # The -k (keep) option will eventually cause all the tests to
 154	    # leave around the contents of the /tmp directory; right now only
 155	    # some implement it.  Not originally intended to be useful with
 156	    # more than one test, but this should work if each test uses a
 157	    # uniquely named dir (use the name of the test).
 158	    keep=:
 159	    ;;
 160	l)
 161	    linkroot=:
 162	    ;;
 163	r)
 164	    remote=:
 165	    ;;
 166	v)
 167	    verbose=:
 168	    ;;
 169	\?)
 170	    exit_usage
 171	    ;;
 172    esac
 173done
 174
 175# boot the arguments we used above
 176while test $OPTIND -gt 1 ; do
 177    shift
 178    OPTIND=`expr $OPTIND - 1`
 179done
 180
 181# Use full path for CVS executable, so that CVS_SERVER gets set properly
 182# for remote.
 183case $1 in
 184"")
 185  exit_usage
 186  ;;
 187/*)
 188  testcvs=$1
 189  ;;
 190*)
 191  testcvs=`pwd`/$1
 192  ;;
 193esac
 194shift
 195
 196# If $remotehost is set, warn if $TESTDIR isn't since we are pretty sure
 197# that its default value of `/tmp/cvs-sanity' will not resolve to the same
 198# directory on two different machines.
 199if test -n "$remotehost" && test -z "$TESTDIR"; then
 200    echo "WARNING: CVS server hostname is set and \$TESTDIR is not.  If" >&2
 201    echo "$remotehost is not the local machine, then it is unlikely that" >&2
 202    echo "the default value assigned to \$TESTDIR will resolve to the same" >&2
 203    echo "directory on both this client and the CVS server." >&2
 204fi
 205
 206
 207
 208###
 209### GUTS
 210###
 211
 212# "debugger"
 213#set -x
 214
 215echo 'This test should produce no other output than this message, and a final "OK".'
 216echo '(Note that the test can take an hour or more to run and periodically stops'
 217echo 'for as long as one minute.  Do not assume there is a problem just because'
 218echo 'nothing seems to happen for a long time.  If you cannot live without'
 219echo 'running status, use the -v option or try the command:'
 220echo "\`tail -f check.log' from another window.)"
 221
 222# Regexp to match what CVS will call itself in output that it prints.
 223# FIXME: we don't properly quote this--if the name contains . we'll
 224# just spuriously match a few things; if the name contains other regexp
 225# special characters we are probably in big trouble.
 226PROG=`basename ${testcvs}`
 227
 228# Match the hostname
 229hostname="[-_.a-zA-Z0-9]*"
 230
 231# Regexp to match the name of a temporary file (from cvs_temp_name).
 232# This appears in certain diff output.
 233tempname="[-a-zA-Z0-9/.%_]*"
 234
 235# Regexp to match a date in RFC822 format (as amended by RFC1123).
 236RFCDATE="[a-zA-Z0-9 ][a-zA-Z0-9 ]* [0-9:][0-9:]* -0000"
 237RFCDATE_EPOCH="1 Jan 1970 00:00:00 -0000"
 238
 239# Regexp to match a date in standard Unix format as used by rdiff
 240# FIXCVS: There's no reason for rdiff to use a different date format
 241# than diff does
 242DATE="[a-zA-Z]* [a-zA-Z]* [ 1-3][0-9] [0-9:]* [0-9]*"
 243
 244# Which directories should Which and find_tool search for executables?
 245SEARCHPATH=$PATH:/usr/local/bin:/usr/contrib/bin:/usr/contrib:/usr/gnu/bin:/local/bin:/local/gnu/bin:/gnu/bin:/sw/bin:/usr/pkg/bin
 246
 247# Do not assume that `type -p cmd` is portable
 248# Usage: Which [-a] [-x|-f|-r] prog [$SEARCHPATH:/with/directories:/to/search]
 249Which() {
 250  # Optional first argument for file type, defaults to -x.
 251  # Second argument is the file or directory to be found.
 252  # Third argument is the PATH to search.
 253  # By default, print only the first file that matches,
 254  # -a will cause all matches to be printed.
 255  notevery=:
 256  if [ "x$1" = "x-a" ]; then notevery=false; shift; fi
 257  case "$1" in
 258    -*) t=$1; shift ;;
 259    *) t=-x ;;
 260  esac
 261  case "$1" in
 262    # FIXME: Someday this may need to be fixed
 263    # to deal better with C:\some\path\to\ssh values...
 264    /*) test $t $1 && echo $1 ;;
 265    *) for d in `IFS=:; echo ${2-$SEARCHPATH}`
 266       do
 267         test $t $d/$1 && { echo $d/$1; if $notevery; then break; fi; }
 268       done
 269       ;;
 270  esac
 271}
 272
 273
 274# On cygwin32, we may not have /bin/sh.
 275if test -r /bin/sh; then
 276  TESTSHELL="/bin/sh"
 277else
 278  TESTSHELL=`Which -f sh`
 279  if test ! -r "$TESTSHELL"; then
 280    TESTSHELL="/bin/sh"
 281  fi
 282fi
 283
 284# FIXME: try things (what things? checkins?) without -m.
 285#
 286# Some of these tests are written to expect -Q.  But testing with
 287# -Q is kind of bogus, it is not the way users actually use CVS (usually).
 288# So new tests probably should invoke ${testcvs} directly, rather than ${CVS}.
 289# and then they've obviously got to do something with the output....
 290#
 291CVS="${testcvs} -Q"
 292
 293LOGFILE=`pwd`/check.log
 294
 295# Save the previous log in case the person running the tests decides
 296# they want to look at it.  The extension ".plog" is chosen for consistency
 297# with dejagnu.
 298if test -f check.log; then
 299	mv check.log check.plog
 300fi
 301
 302# Create the log file so check.log can be tailed almost immediately after
 303# this script is started.  Otherwise it can take up to a minute or two before
 304# the log file gets created when $remotehost is specified on some systems,
 305# which makes for a lot of failed `tail -f' attempts.
 306touch check.log
 307
 308# Workaround any X11Forwarding by ssh. Otherwise this text:
 309#   Warning: No xauth data; using fake authentication data for X11 forwarding.
 310# has been known to end up in the test results below
 311# causing the test to fail.
 312[ -n "$DISPLAY" ] && unset DISPLAY
 313  
 314# The default value of /tmp/cvs-sanity for TESTDIR is dubious,
 315# because it loses if two people/scripts try to run the tests
 316# at the same time.  Some possible solutions:
 317# 1.  Use /tmp/cvs-test$$.  One disadvantage is that the old
 318#     cvs-test* directories would pile up, because they wouldn't
 319#     necessarily get removed.
 320# 2.  Have everyone/everything running the testsuite set
 321#     TESTDIR to some appropriate directory.
 322# 3.  Have the default value of TESTDIR be some variation of
 323#     `pwd`/cvs-sanity.  The biggest problem here is that we have
 324#     been fairly careful to test that CVS prints in messages the
 325#     actual pathnames that we pass to it, rather than a different
 326#     pathname for the same directory, as may come out of `pwd`.
 327#     So this would be lost if everything was `pwd`-based.  I suppose
 328#     if we wanted to get baroque we could start making symlinks
 329#     to ensure the two are different.
 330: ${CVS_RSH=rsh}; export CVS_RSH
 331if test -n "$remotehost"; then
 332        # We need to set $tmp on the server since $TMPDIR is compared against
 333	# messages generated by the server.
 334	tmp=`$CVS_RSH $remotehost 'cd /tmp; /bin/pwd || pwd' 2>/dev/null`
 335	if test $? != 0; then
 336	    echo "$CVS_RSH $remotehost failed." >&2
 337	    exit 1
 338	fi
 339else
 340	tmp=`(cd /tmp; /bin/pwd || pwd) 2>/dev/null`
 341fi
 342
 343# Now:
 344#	1) Set TESTDIR if it's not set already
 345#	2) Remove any old test remnants
 346#	3) Create $TESTDIR
 347#	4) Normalize TESTDIR with `cd && (/bin/pwd || pwd)`
 348#	   (This will match CVS output later)
 349: ${TESTDIR=$tmp/cvs-sanity}
 350# clean any old remnants (we need the chmod because some tests make
 351# directories read-only)
 352if test -d ${TESTDIR}; then
 353    chmod -R a+wx ${TESTDIR}
 354    rm -rf ${TESTDIR}
 355fi
 356# These exits are important.  The first time I tried this, if the `mkdir && cd`
 357# failed then the build directory would get blown away.  Some people probably
 358# wouldn't appreciate that.
 359mkdir ${TESTDIR} || exit 1
 360cd ${TESTDIR} || exit 1
 361# Ensure $TESTDIR is absolute
 362if echo "${TESTDIR}" |grep '^[^/]'; then
 363    # Don't resolve this unless we have to.  This keeps symlinks intact.  This
 364    # is important at least when testing using -h $remotehost, because the same
 365    # value for $TESTDIR must resolve to the same directory on the client and
 366    # the server and we likely used Samba, and possibly symlinks, to do this.
 367    TESTDIR=`(/bin/pwd || pwd) 2>/dev/null`
 368fi
 369
 370if test -z "${TESTDIR}" || echo "${TESTDIR}" |grep '^[^/]'; then
 371    echo "Unable to resolve TESTDIR to an absolute directory." >&2
 372    exit 1
 373fi
 374cd ${TESTDIR}
 375
 376# Now set $TMPDIR if the user hasn't overridden it.
 377#
 378# We use a $TMPDIR under $TESTDIR by default so that two tests may be run at
 379# the same time without bumping heads without requiring the user to specify
 380# more than $TESTDIR.  See the test for leftover cvs-serv* directories near the
 381# end of this script at the end of "The big loop".
 382: ${TMPDIR=$TESTDIR/tmp}
 383export TMPDIR
 384if test -d $TMPDIR; then :; else
 385    mkdir $TMPDIR
 386fi
 387
 388# Make sure various tools work the way we expect, or try to find
 389# versions that do.
 390: ${AWK=awk}
 391: ${EXPR=expr}
 392: ${ID=id}
 393: ${TR=tr}
 394
 395# Keep track of tools that are found, but do NOT work as we hope
 396# in order to avoid them in future
 397badtools=
 398set_bad_tool ()
 399{
 400   badtools=$badtools:$1
 401}
 402is_bad_tool ()
 403{
 404   case ":$badtools:" in *:$1:*) return 0 ;; *) return 1 ; esac
 405}
 406
 407version_test ()
 408{
 409  vercmd=$1
 410  verbad=:
 411  if RES=`$vercmd --version </dev/null 2>&1`; then
 412    if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
 413      echo "$RES"
 414      verbad=false
 415    fi
 416  fi
 417  if $verbad; then
 418    echo "The command \`$vercmd' does not support the --version option."
 419  fi
 420  # It does not really matter that --version is not supported
 421  return 0
 422}
 423
 424# Try to find a tool that satisfies all of the tests.
 425# Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
 426# Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
 427find_tool ()
 428{
 429  default_TOOL=$1
 430  echo find_tool: ${1+"$@"} >>$LOGFILE
 431  cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
 432  if test -z "$tooltests"; then tooltests=version_test; fi
 433  clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
 434  # Make sure the default tool is just the first real command name
 435  for default_TOOL in $clist `IFS=:; echo $default_TOOL`; do break; done
 436  TOOL=""
 437  for trytool in $clist ; do
 438    pass=:
 439    for tooltest in $tooltests; do
 440      result=`eval $tooltest $trytool`
 441      rc=$?
 442      echo "Running $tooltest $trytool" >>$LOGFILE
 443      if test -n "$result"; then
 444	echo "$result" >>$LOGFILE
 445      fi
 446      if test "$rc" = "0"; then
 447        echo "PASS: $tooltest $trytool" >>$LOGFILE
 448      elif test "$rc" = "77"; then
 449        echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
 450        TOOL=$trytool
 451	pass=false
 452      else
 453        set_bad_tool $trytool
 454        echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
 455	pass=false
 456      fi
 457    done
 458    if $pass; then
 459      echo $trytool
 460      return 0
 461    fi
 462  done
 463  if test -n "$TOOL"; then
 464    echo "Notice: The default version of \`$default_TOOL' is defective." >>$LOGFILE
 465    echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
 466    echo "Notice: The default version of \`$default_TOOL' is defective." >&2
 467    echo "using \`$TOOL' and hoping for the best." >&2
 468    echo $TOOL
 469  else
 470    echo $default_TOOL
 471  fi
 472}  
 473
 474id_tool_test ()
 475{
 476  id=$1
 477  if $id -u >/dev/null 2>&1 && $id -un >/dev/null 2>&1; then
 478    return 0
 479  else
 480    echo "Running these tests requires an \`id' program that understands the"
 481    echo "-u and -n flags.  Make sure that such an id (GNU, or many but not"
 482    echo "all vendor-supplied versions) is in your path."
 483    return 1
 484  fi
 485}
 486
 487ID=`find_tool id version_test id_tool_test`
 488echo "Using ID=$ID" >>$LOGFILE
 489
 490# You can't run CVS as root; print a nice error message here instead
 491# of somewhere later, after making a mess.
 492for pass in false :; do
 493  case "`$ID -u 2>/dev/null`" in
 494    "0")
 495      echo "Test suite does not work correctly when run as root" >&2
 496      exit 1
 497      ;;
 498
 499    *)
 500      break
 501      ;;
 502  esac
 503done
 504
 505# Cause NextStep 3.3 users to lose in a more graceful fashion.
 506expr_tooltest1 ()
 507{
 508expr=$1
 509if $expr 'abc
 510def' : 'abc
 511def' >/dev/null; then
 512  # good, it works
 513  return 0
 514else
 515  echo 'Running these tests requires an "expr" program that can handle'
 516  echo 'multi-line patterns.  Make sure that such an expr (GNU, or many but'
 517  echo 'not all vendor-supplied versions) is in your path.'
 518  return 1
 519fi
 520}
 521
 522# Warn SunOS, SysVr3.2, etc., users that they may be partially losing
 523# if we can't find a GNU expr to ease their troubles...
 524expr_tooltest2 ()
 525{
 526expr=$1
 527if $expr 'a
 528b' : 'a
 529c' >/dev/null; then
 530  echo 'WARNING: you are using a version of expr that does not correctly'
 531  echo 'match multi-line patterns.  Some tests may spuriously pass or fail.'
 532  echo 'You may wish to make sure GNU expr is in your path.'
 533  return 1
 534else
 535  return 0
 536fi
 537}
 538
 539expr_create_bar ()
 540{
 541echo 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >${TESTDIR}/foo
 542cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
 543cat ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar >${TESTDIR}/foo
 544cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
 545rm -f ${TESTDIR}/foo
 546}
 547
 548expr_tooltest3 ()
 549{
 550expr=$1
 551# More SunOS lossage...
 552test ! -f ${TESTDIR}/bar && expr_create_bar
 553if $expr "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
 554  : good, it works
 555else
 556  echo 'WARNING: you are using a version of expr that does not correctly'
 557  echo 'match large patterns.  Some tests may spuriously pass or fail.'
 558  echo 'You may wish to make sure GNU expr is in your path.'
 559  return 1
 560fi
 561if $expr "`cat ${TESTDIR}/bar`x" : "`cat ${TESTDIR}/bar`y" >/dev/null; then
 562  echo 'WARNING: you are using a version of expr that does not correctly'
 563  echo 'match large patterns.  Some tests may spuriously pass or fail.'
 564  echo 'You may wish to make sure GNU expr is in your path.'
 565  return 1
 566fi
 567# good, it works
 568return 0
 569}
 570
 571# That we should have to do this is total bogosity, but GNU expr
 572# version 1.9.4-1.12 uses the emacs definition of "$" instead of the unix
 573# (e.g. SunOS 4.1.3 expr) one.  Rumor has it this will be fixed in the
 574# next release of GNU expr after 1.12 (but we still have to cater to the old
 575# ones for some time because they are in many linux distributions).
 576ENDANCHOR="$"
 577expr_set_ENDANCHOR ()
 578{
 579expr=$1
 580ENDANCHOR="$"
 581if $expr 'abc
 582def' : 'abc$' >/dev/null; then
 583  ENDANCHOR='\'\'
 584   echo "Notice: An ENDANCHOR of dollar does not work."
 585   echo "Using a workaround for GNU expr versions 1.9.4 thru 1.12"
 586fi
 587return 0
 588}
 589
 590# Work around another GNU expr (version 1.10-1.12) bug/incompatibility.
 591# "." doesn't appear to match a newline (it does with SunOS 4.1.3 expr).
 592# Note that the workaround is not a complete equivalent of .* because
 593# the first parenthesized expression in the regexp must match something
 594# in order for expr to return a successful exit status.
 595# Rumor has it this will be fixed in the
 596# next release of GNU expr after 1.12 (but we still have to cater to the old
 597# ones for some time because they are in many linux distributions).
 598DOTSTAR='.*'
 599expr_set_DOTSTAR ()
 600{
 601expr=$1
 602DOTSTAR='.*'
 603if $expr 'abc
 604def' : "a${DOTSTAR}f" >/dev/null; then
 605  : good, it works
 606else
 607  DOTSTAR='\(.\|
 608\)*'
 609  echo "Notice: DOTSTAR changed from sane \`.*' value to \`$DOTSTAR\`"
 610  echo "to workaround GNU expr version 1.10 thru 1.12 bug where \`.'"
 611  echo "does not match a newline."
 612fi
 613return 0
 614}
 615
 616# Now that we have DOTSTAR, make sure it works with big matches
 617expr_tooltest_DOTSTAR ()
 618{
 619expr=$1
 620test ! -f ${TESTDIR}/bar && expr_create_bar
 621if $expr "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; then
 622  # good, it works
 623  return 0
 624else
 625  echo 'WARNING: you are using a version of expr that does not correctly'
 626  echo 'match large patterns.  Some tests may spuriously pass or fail.'
 627  echo 'You may wish to make sure GNU expr is in your path.'
 628  return 77
 629fi
 630}
 631
 632# FreeBSD 5.2 and 6.1 support 'expr [-e] expression' 
 633# They get confused unless '--' is used before the expressions
 634# when those expressions begin with a '-' character, such as the
 635# output of an ls -l command. The EXPR_COMPAT environment variable may
 636# be used to go back to the non-POSIX behavior as an alternative.
 637# (GNU expr appears to accept the '--' argument and work correctly or
 638# not have it and still get the results we want.)
 639exprDASHDASH='false'
 640expr_set_DASHDASH ()
 641{
 642expr=$1
 643exprDASHDASH='false'
 644# Not POSIX, but works on a lot of expr versions.
 645if $expr "-rw-rw-r--" : "-rw-rw-r--" >/dev/null 2>&1; then
 646  # good, it works
 647  return 0
 648else
 649  # Do things in the POSIX manner.
 650  if $expr -- "-rw-rw-r--" : "-rw-rw-r--" >/dev/null 2>&1; then
 651    exprDASHDASH=':'
 652    return 0
 653  else
 654    echo 'WARNING: Your $expr does not correctly handle'
 655    echo 'leading "-" characters in regular expressions to'
 656    echo 'be matched. You may wish to see if there is an'
 657    echo 'environment variable or other setting to allow'
 658    echo 'POSIX functionality to be enabled.'
 659    return 77
 660  fi
 661fi
 662}
 663
 664
 665EXPR=`find_tool ${EXPR}:gexpr \
 666  version_test expr_tooltest1 expr_tooltest2 expr_tooltest3 \
 667expr_set_ENDANCHOR expr_set_DOTSTAR expr_tooltest_DOTSTAR`
 668
 669# Set the ENDANCHOR and DOTSTAR for the chosen expr version.
 670expr_set_ENDANCHOR ${EXPR} >/dev/null
 671expr_tooltest_DOTSTAR ${EXPR} >/dev/null
 672
 673# Is $EXPR a POSIX or non-POSIX implementation
 674# with regard to command-line arguments?
 675expr_set_DASHDASH ${EXPR}
 676$exprDASHDASH && EXPR="$EXPR --"
 677
 678echo "Using EXPR=$EXPR" >>$LOGFILE
 679echo "Using ENDANCHOR=$ENDANCHOR" >>$LOGFILE
 680echo "Using DOTSTAR=$DOTSTAR" >>$LOGFILE
 681
 682# Cleanup
 683rm -f ${TESTDIR}/bar
 684
 685# Work around yet another GNU expr (version 1.10) bug/incompatibility.
 686# "+" is a special character, yet for unix expr (e.g. SunOS 4.1.3)
 687# it is not.  I doubt that POSIX allows us to use \+ and assume it means
 688# (non-special) +, so here is another workaround
 689# Rumor has it this will be fixed in the
 690# next release of GNU expr after 1.12 (but we still have to cater to the old
 691# ones for some time because they are in many linux distributions).
 692PLUS='+'
 693if $EXPR 'a +b' : "a ${PLUS}b" >/dev/null; then
 694  : good, it works
 695else
 696  PLUS='\+'
 697fi
 698
 699# Likewise, for ?
 700QUESTION='?'
 701if $EXPR 'a?b' : "a${QUESTION}b" >/dev/null; then
 702  : good, it works
 703else
 704  QUESTION='\?'
 705fi
 706
 707# Now test the username to make sure it contains only valid characters
 708username=`$ID -un`
 709if $EXPR "${username}" : "${username}" >/dev/null; then
 710  : good, it works
 711else
 712  echo "Test suite does not work correctly when run by a username" >&2
 713  echo "containing regular expression meta-characters." >&2
 714  exit 1
 715fi
 716
 717# Only 8 characters of $username appear in some output.
 718if test `echo $username |wc -c` -gt 8; then
 719  username8=`echo $username |sed 's/^\(........\).*/\1/'`
 720else
 721  username8=$username
 722fi
 723
 724# Rarely, we need to match any username, not just the name of the user
 725# running this test.
 726#
 727# I'm not really sure what characters should be here.  a-zA-Z obviously.
 728# People complained when 0-9 were not allowed in usernames.  Other than that
 729# I'm not sure.
 730anyusername="[-a-zA-Z0-9][-a-zA-Z0-9]*"
 731
 732# now make sure that tr works on NULs
 733tr_tooltest1 ()
 734{
 735tr=$1
 736if $EXPR `echo "123" | $tr '2' '\0'` : "123" >/dev/null 2>&1; then
 737  echo 'Warning: you are using a version of tr which does not correctly'
 738  echo 'handle NUL bytes.  Some tests may spuriously pass or fail.'
 739  echo 'You may wish to make sure GNU tr is in your path.'
 740  return 77
 741fi
 742# good, it works
 743return 0
 744}
 745
 746TR=`find_tool ${TR}:gtr version_test tr_tooltest1`
 747echo "Using TR=$TR" >>$LOGFILE
 748
 749# Awk testing
 750
 751awk_tooltest1 ()
 752{
 753awk=$1
 754$awk 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
 755if $EXPR "`cat abc`" : \
 756'one
 757two
 758three
 759four
 760five
 761six'; then
 762  rm abc
 763  return 0
 764else
 765  rm abc
 766  echo "Notice: awk BEGIN clause or printf is not be working properly."
 767  return 1
 768fi
 769}
 770
 771# Format item %c check
 772awk_tooltest2 ()
 773{
 774awk=$1
 775$awk 'BEGIN { printf "%c%c%c", 2, 3, 4 }' </dev/null \
 776  | ${TR} '\002\003\004' '123' >abc
 777if $EXPR "`cat abc`" : "123" ; then
 778  : good, found it
 779else
 780  echo "Notice: awk format %c string may not be working properly."
 781  rm abc
 782  return 77
 783fi
 784rm abc
 785return 0
 786}
 787
 788AWK=`find_tool gawk:nawk:awk version_test awk_tooltest1 awk_tooltest2`
 789echo "Using AWK=$AWK" >>$LOGFILE
 790
 791# Test that $1 works as a remote shell.  If so, set $host, $CVS_RSH, &
 792# $save_CVS_RSH to match and return 0.  Otherwise, set $skipreason and return
 793# 77.
 794depends_on_rsh ()
 795{
 796  host=${remotehost-"`hostname`"}
 797  result=`$1 $host 'echo test'`
 798  rc=$?
 799  if test $? != 0 || test "x$result" != "xtest"; then
 800    skipreason="\`$1 $host' failed rc=$rc result=$result"
 801    return 77
 802  fi
 803
 804  save_CVS_RSH=$CVS_RSH
 805  CVS_RSH=$1; export CVS_RSH
 806  return 0
 807}
 808
 809# Find a usable SSH.  When a usable ssh is found, set $host, $CVS_RSH, and
 810# $save_CVS_RSH and return 0.  Otherwise, set $skipreason and return 77.
 811depends_on_ssh ()
 812{
 813  case "$CVS_RSH" in
 814    *ssh*|*putty*)
 815      tryssh=`Which $CVS_RSH`
 816      if [ ! -n "$tryssh" ]; then
 817	skipreason="Unable to find CVS_RSH=$CVS_RSH executable"
 818	return 77
 819      elif [ ! -x "$tryssh" ]; then
 820	skipreason="Unable to execute $tryssh program"
 821	return 77
 822      fi
 823      ;;
 824    *)
 825      # Look in the user's PATH for "ssh"
 826      tryssh=`Which ssh`
 827      if test ! -r "$tryssh"; then
 828	skipreason="Unable to find ssh program"
 829	return 77
 830      fi
 831      ;;
 832  esac
 833
 834  depends_on_rsh "$tryssh"
 835  return $?
 836}
 837
 838pass ()
 839{
 840  echo "PASS: $1" >>${LOGFILE}
 841  passed=`expr $passed + 1`
 842}
 843
 844# Like skip(), but don't fail when $skipfail is set.
 845skip_always ()
 846{
 847  echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
 848  skipped=`expr $skipped + 1`
 849}
 850
 851skip ()
 852{
 853  if $skipfail; then
 854    fail "$1${2+ ($2)}"
 855  else
 856    echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
 857  fi
 858  skipped=`expr $skipped + 1`
 859}
 860
 861warn ()
 862{
 863  if $skipfail; then
 864    fail "$1${2+ ($2)}"
 865  else
 866    echo "WARNING: $1${2+ ($2)}" >>$LOGFILE
 867  fi
 868  warnings=`expr $warnings + 1`
 869}
 870
 871# Convenience function for skipping tests run only in local mode.
 872localonly ()
 873{
 874  skip_always $1 "only tested in local mode"
 875}
 876
 877fail ()
 878{
 879  echo "FAIL: $1" | tee -a ${LOGFILE}
 880  echo "*** Please see the \`TESTS' and \`check.log' files for more information." >&2
 881  # This way the tester can go and see what remnants were left
 882  exit 1
 883}
 884
 885verify_tmp_empty ()
 886{
 887  # Test our temp directory for cvs-serv* directories and cvsXXXXXX temp
 888  # files.  We would like to not leave any behind.
 889  if $remote && ls $TMPDIR/cvs-serv* >/dev/null 2>&1; then
 890    # A true value means ls found files/directories with these names.
 891    # Give the server some time to finish, then retry.
 892    sleep 1
 893    if ls $TMPDIR/cvs-serv* >/dev/null 2>&1; then
 894      warn "$1" "Found cvs-serv* directories in $TMPDIR."
 895      # The above will exit if $skipfail
 896      rm -rf $TMPDIR/cvs-serv*
 897    fi
 898  fi
 899  if ls $TMPDIR/cvs?????? >/dev/null 2>&1; then
 900    # A true value means ls found files/directories with these names.
 901    warn "$1" "Found cvsXXXXXX temp files in $TMPDIR."
 902    # The above will exit if $skipfail
 903    rm -f ls $TMPDIR/cvs??????
 904  fi
 905}
 906
 907# Restore changes to CVSROOT admin files.
 908restore_adm ()
 909{
 910    rm -rf $CVSROOT_DIRNAME/CVSROOT
 911    cp -Rp $TESTDIR/CVSROOT.save $CVSROOT_DIRNAME/CVSROOT
 912}
 913
 914# See dotest and dotest_fail for explanation (this is the parts
 915# of the implementation common to the two).
 916dotest_internal ()
 917{
 918  if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$3${ENDANCHOR}" >/dev/null; then
 919    # Why, I hear you ask, do we write this to the logfile
 920    # even when the test passes?  The reason is that the test
 921    # may give us the regexp which we were supposed to match,
 922    # but sometimes it may be useful to look at the exact
 923    # text which was output.  For example, suppose one wants
 924    # to grep for a particular warning, and make _sure_ that
 925    # CVS never hits it (even in cases where the tests might
 926    # match it with .*).  Or suppose one wants to see the exact
 927    # date format output in a certain case (where the test will
 928    # surely use a somewhat non-specific pattern).
 929    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
 930    pass "$1"
 931    verify_tmp_empty "$1"
 932  # expr can't distinguish between "zero characters matched" and "no match",
 933  # so special-case it.
 934  elif test -z "$3" && test ! -s ${TESTDIR}/dotest.tmp; then
 935    pass "$1"
 936    verify_tmp_empty "$1"
 937  elif test x"$4" != x; then
 938    if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$4${ENDANCHOR}" >/dev/null; then
 939      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
 940      pass "$1"
 941      verify_tmp_empty "$1"
 942    else
 943      echo "** expected: " >>${LOGFILE}
 944      echo "$3" >>${LOGFILE}
 945      echo "$3" > ${TESTDIR}/dotest.ex1
 946      echo "** or: " >>${LOGFILE}
 947      echo "$4" >>${LOGFILE}
 948      echo "$4" > ${TESTDIR}/dotest.ex2
 949      echo "** got: " >>${LOGFILE}
 950      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
 951      fail "$1"
 952    fi
 953  else
 954    echo "** expected: " >>${LOGFILE}
 955    echo "$3" >>${LOGFILE}
 956    echo "$3" > ${TESTDIR}/dotest.exp
 957    echo "** got: " >>${LOGFILE}
 958    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
 959    fail "$1"
 960  fi
 961}
 962
 963dotest_all_in_one ()
 964{
 965  if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : \
 966         "`cat ${TESTDIR}/dotest.exp`" >/dev/null; then
 967    return 0
 968  fi
 969  return 1
 970}
 971
 972# WARNING: this won't work with REs that match newlines....
 973#
 974dotest_line_by_line ()
 975{
 976  line=1
 977  while [ $line -le `wc -l <${TESTDIR}/dotest.tmp` ] ; do
 978    if $EXPR "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" : \
 979       "`sed -n ${line}p ${TESTDIR}/dotest.exp`" >/dev/null; then
 980      :
 981    elif test -z "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" &&
 982       test -z "`sed -n ${line}p ${TESTDIR}/dotest.exp`"; then
 983      :
 984    else
 985      echo "Line $line:" >> ${LOGFILE}
 986      echo "**** expected: " >>${LOGFILE}
 987      sed -n ${line}p ${TESTDIR}/dotest.exp >>${LOGFILE}
 988      echo "**** got: " >>${LOGFILE}
 989      sed -n ${line}p ${TESTDIR}/dotest.tmp >>${LOGFILE}
 990      unset line
 991      return 1
 992    fi
 993    line=`expr $line + 1`
 994  done
 995  unset line
 996  return 0
 997}
 998
 999# If you are having trouble telling which line of a multi-line
1000# expression is not being matched, replace calls to dotest_internal()
1001# with calls to this function:
1002#
1003dotest_internal_debug ()
1004{
1005  if test -z "$3"; then
1006    if test -s ${TESTDIR}/dotest.tmp; then
1007      echo "** expected: " >>${LOGFILE}
1008      echo "$3" >>${LOGFILE}
1009      echo "$3" > ${TESTDIR}/dotest.exp
1010      rm -f ${TESTDIR}/dotest.ex2
1011      echo "** got: " >>${LOGFILE}
1012      cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1013      fail "$1"
1014    else
1015      pass "$1"
1016      verify_tmp_empty "$1"
1017    fi
1018  else
1019    echo "$3" > ${TESTDIR}/dotest.exp
1020    if dotest_line_by_line "$1" "$2"; then
1021      pass "$1"
1022      verify_tmp_empty "$1"
1023    else
1024      if test x"$4" != x; then
1025	mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex1
1026	echo "$4" > ${TESTDIR}/dotest.exp
1027	if dotest_line_by_line "$1" "$2"; then
1028	  pass "$1"
1029	  verify_tmp_empty "$1"
1030	else
1031	  mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex2
1032	  echo "** expected: " >>${LOGFILE}
1033	  echo "$3" >>${LOGFILE}
1034	  echo "** or: " >>${LOGFILE}
1035	  echo "$4" >>${LOGFILE}
1036	  echo "** got: " >>${LOGFILE}
1037	  cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1038	  fail "$1"
1039	fi
1040      else
1041	echo "** expected: " >>${LOGFILE}
1042	echo "$3" >>${LOGFILE}
1043	echo "** got: " >>${LOGFILE}
1044	cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1045	fail "$1"
1046      fi
1047    fi
1048  fi
1049}
1050
1051# Usage:
1052#  dotest TESTNAME COMMAND OUTPUT [OUTPUT2]
1053# TESTNAME is the name used in the log to identify the test.
1054# COMMAND is the command to run; for the test to pass, it exits with
1055# exitstatus zero.
1056# OUTPUT is a regexp which is compared against the output (stdout and
1057# stderr combined) from the test.  It is anchored to the start and end
1058# of the output, so should start or end with ".*" if that is what is desired.
1059# Trailing newlines are stripped from the command's actual output before
1060# matching against OUTPUT.
1061# If OUTPUT2 is specified and the output matches it, then it is also
1062# a pass (partial workaround for the fact that some versions of expr
1063# lack \|).
1064dotest ()
1065{
1066  rm -f ${TESTDIR}/dotest.ex? 2>&1
1067  eval "$2" >${TESTDIR}/dotest.tmp 2>&1
1068  status=$?
1069  if test "$status" != 0; then
1070    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1071    echo "exit status was $status" >>${LOGFILE}
1072    fail "$1"
1073  fi
1074  dotest_internal "$@"
1075}
1076
1077# Like dotest except only 2 args and result must exactly match stdin
1078dotest_lit ()
1079{
1080  rm -f ${TESTDIR}/dotest.ex? 2>&1
1081  eval "$2" >${TESTDIR}/dotest.tmp 2>&1
1082  status=$?
1083  if test "$status" != 0; then
1084    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1085    echo "exit status was $status" >>${LOGFILE}
1086    fail "$1"
1087  fi
1088  cat >${TESTDIR}/dotest.exp
1089  if cmp ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.tmp >/dev/null 2>&1; then
1090    pass "$1"
1091    verify_tmp_empty "$1"
1092  else
1093    echo "** expected: " >>${LOGFILE}
1094    cat ${TESTDIR}/dotest.exp >>${LOGFILE}
1095    echo "** got: " >>${LOGFILE}
1096    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1097    fail "$1"
1098  fi
1099}
1100
1101# Like dotest except exitstatus should be nonzero.
1102dotest_fail ()
1103{
1104  rm -f ${TESTDIR}/dotest.ex? 2>&1
1105  eval "$2" >${TESTDIR}/dotest.tmp 2>&1
1106  status=$?
1107  if test "$status" = 0; then
1108    cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1109    echo "exit status was $status" >>${LOGFILE}
1110    fail "$1"
1111  fi
1112  dotest_internal "$@"
1113}
1114
1115# Like dotest except output is sorted.
1116dotest_sort ()
1117{
1118  rm -f ${TESTDIR}/dotest.ex? 2>&1
1119  eval "$2" >${TESTDIR}/dotest.tmp1 2>&1
1120  status=$?
1121  if test "$status" != 0; then
1122    cat ${TESTDIR}/dotest.tmp1 >>${LOGFILE}
1123    echo "exit status was $status" >>${LOGFILE}
1124    fail "$1"
1125  fi
1126  ${TR} '	' ' ' < ${TESTDIR}/dotest.tmp1 | sort > ${TESTDIR}/dotest.tmp
1127  dotest_internal "$@"
1128}
1129
1130# A function for fetching the timestamp of a revison of a file
1131getrlogdate () {
1132    ${testcvs} -n rlog -N ${1+"$@"} |
1133    while read token value; do
1134	case "$token" in
1135	date:)
1136	    echo $value | sed "s,;.*,,"
1137	    break;
1138            ;;
1139	esac
1140    done
1141}
1142
1143# Avoid picking up any stray .cvsrc, etc., from the user running the tests
1144mkdir home
1145HOME=${TESTDIR}/home; export HOME
1146
1147# Make sure this variable is not defined to anything that would
1148# change the format of rcs dates.  Otherwise people using e.g.,
1149# RCSINIT=-zLT get lots of spurious failures.
1150RCSINIT=; export RCSINIT
1151
1152# Remaining arguments are the names of tests to run.
1153#
1154# The testsuite is broken up into (hopefully manageably-sized)
1155# independently runnable tests, so that one can quickly get a result
1156# from a cvs or testsuite change, and to facilitate understanding the
1157# tests.
1158
1159if test x"$*" = x; then
1160	# Basic/miscellaneous functionality
1161	tests="version basica basicb basicc basic1 deep basic2"
1162	tests="${tests} parseroot parseroot2 files spacefiles commit-readonly"
1163	tests="${tests} commit-add-missing"
1164	tests="$tests add-restricted"
1165	tests="${tests} status"
1166	# Branching, tagging, removing, adding, multiple directories
1167	tests="${tests} rdiff rdiff-short"
1168	tests="${tests} rdiff2 diff diffnl death death2 death-rtag"
1169	tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
1170	tests="${tests} dirs dirs2 branches branches2 tagc tagf "
1171	tests="${tests} tag-log tag-space"
1172	tests="${tests} rcslib multibranch import importb importc import-CVS"
1173	tests="$tests import-quirks"
1174	tests="${tests} update-p import-after-initial branch-after-import"
1175	tests="${tests} join join2 join3 join4 join5 join6 join7 join8 join9"
1176	tests="${tests} join-readonly-conflict join-admin join-admin-2"
1177	tests="${tests} join-rm"
1178	tests="${tests} new newb conflicts conflicts2 conflicts3 conflicts4"
1179	tests="${tests} clean"
1180	# Checking out various places (modules, checkout -d, &c)
1181	tests="${tests} modules modules2 modules3 modules4 modules5 modules6"
1182	tests="${tests} modules7 mkmodules co-d"
1183	tests="${tests} cvsadm emptydir abspath abspath2 toplevel toplevel2"
1184        tests="${tests} rstar-toplevel trailingslashes checkout_repository"
1185	# Log messages, error messages.
1186	tests="${tests} mflag editor errmsg1 errmsg2 adderrmsg opterrmsg"
1187	# Watches, binary files, history browsing, &c.
1188	tests="${tests} devcom devcom2 devcom3 watch4 watch5 watch6"
1189	tests="${tests} unedit-without-baserev"
1190	tests="${tests} ignore ignore-on-branch binfiles binfiles2 binfiles3"
1191	tests="${tests} mcopy binwrap binwrap2"
1192	tests="${tests} binwrap3 mwrap info taginfo config"
1193	tests="${tests} serverpatch log log2 logopt ann ann-id"
1194	# Repository Storage (RCS file format, CVS lock files, creating
1195	# a repository without "cvs init", &c).
1196	tests="${tests} crerepos crerepos-extssh rcs rcs2 rcs3 rcs4 rcs5 rcs6"
1197	tests="$tests lockfiles backuprecover"
1198	tests="${tests} sshstdio"
1199	# More history browsing, &c.
1200	tests="${tests} history"
1201	tests="${tests} big modes modes2 modes3 stamps"
1202	# PreservePermissions stuff: permissions, symlinks et al.
1203	# tests="${tests} perms symlinks symlinks2 hardlinks"
1204	# More tag and branch tests, keywords.
1205	tests="${tests} sticky keyword keywordlog keywordname keyword2"
1206	tests="${tests} head tagdate multibranch2 tag8k"
1207	# "cvs admin", reserved checkouts.
1208	tests="${tests} admin reserved"
1209	# Nuts and bolts of diffing/merging (diff library, &c)
1210	tests="${tests} diffmerge1 diffmerge2"
1211	# Release of multiple directories
1212	tests="${tests} release"
1213	tests="${tests} recase"
1214	# Multiple root directories and low-level protocol tests.
1215	tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
1216	tests="$tests rmroot reposmv pserver server server2 server3"
1217	tests="$tests client client2"
1218	tests="${tests} dottedroot fork commit-d"
1219else
1220	tests="$*"
1221fi
1222
1223# Now check the -f argument for validity.
1224if test -n "$fromtest"; then
1225	# Don't allow spaces - they are our delimiters in tests
1226	count=0
1227	for sub in $fromtest; do
1228	  count=`expr $count + 1`
1229	done
1230	if test $count != 1; then
1231		echo "No such test \`$fromtest'." >&2
1232		exit 2
1233	fi
1234	# make sure it is in $tests
1235	case " $tests " in
1236		*" $fromtest "*)
1237			;;
1238		*)
1239			echo "No such test \`$fromtest'." >&2
1240			exit 2
1241			;;
1242	esac
1243fi
1244
1245
1246
1247# a simple function to compare directory contents
1248#
1249# Returns: 0 for same, 1 for different
1250#
1251directory_cmp ()
1252{
1253	OLDPWD=`pwd`
1254	DIR_1=$1
1255	DIR_2=$2
1256
1257	cd $DIR_1
1258	find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d1
1259
1260	# go back where we were to avoid symlink hell...
1261	cd $OLDPWD
1262	cd $DIR_2
1263	find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d2
1264
1265	if diff $TESTDIR/dc$$d1 $TESTDIR/dc$$d2 >/dev/null 2>&1
1266	then
1267		:
1268	else
1269		return 1
1270	fi
1271	cd $OLDPWD
1272	while read a
1273	do
1274		if test -f $DIR_1/"$a" ; then
1275			cmp -s $DIR_1/"$a" $DIR_2/"$a"
1276			if test $? -ne 0 ; then
1277				return 1
1278			fi
1279		fi
1280	done < $TESTDIR/dc$$d1
1281	rm -f $TESTDIR/dc$$*
1282	return 0
1283}
1284
1285
1286
1287#
1288# The following 4 functions are used by the diffmerge1 test case.  They set up,
1289# respectively, the four versions of the files necessary:
1290#
1291#	1.  Ancestor revisions.
1292#	2.  "Your" changes.
1293#	3.  "My" changes.
1294#	4.  Expected merge result.
1295#
1296
1297# Create ancestor revisions for diffmerge1
1298diffmerge_create_older_files() {
1299	  # This test case was supplied by Noah Friedman:
1300	  cat >testcase01 <<EOF
1301// Button.java
1302
1303package random.application;
1304
1305import random.util.*;
1306
1307public class Button
1308{
1309  /* Instantiates a Button with origin (0, 0) and zero width and height.
1310   * You must call an initializer method to properly initialize the Button.
1311   */
1312  public Button ()
1313  {
1314    super ();
1315
1316    _titleColor = Color.black;
1317    _disabledTitleColor = Color.gray;
1318    _titleFont = Font.defaultFont ();
1319  }
1320
1321  /* Convenience constructor for instantiating a Button with
1322   * bounds x, y, width, and height.  Equivalent to
1323   *     foo = new Button ();
1324   *     foo.init (x, y, width, height);
1325   */
1326  public Button (int x, int y, int width, int height)
1327  {
1328    this ();
1329    init (x, y, width, height);
1330  }
1331}
1332EOF
1333
1334	  # This test case was supplied by Jacob Burckhardt:
1335	  cat >testcase02 <<EOF
1336a
1337a
1338a
1339a
1340a
1341EOF
1342
1343	  # This test case was supplied by Karl Tomlinson who also wrote the
1344	  # patch which lets CVS correctly handle this and several other cases:
1345	  cat >testcase03 <<EOF
1346x
1347s
1348a
1349b
1350s
1351y
1352EOF
1353
1354	  # This test case was supplied by Karl Tomlinson:
1355	  cat >testcase04 <<EOF
1356s
1357x
1358m
1359m
1360x
1361s
1362v
1363s
1364x
1365m
1366m
1367x
1368s
1369EOF
1370
1371	  # This test case was supplied by Karl Tomlinson:
1372	  cat >testcase05 <<EOF
1373s
1374x
1375m
1376m
1377x
1378x
1379x
1380x
1381x
1382x
1383x
1384x
1385x
1386x
1387s
1388s
1389s
1390s
1391s
1392s
1393s
1394s
1395s
1396s
1397v
1398EOF
1399
1400	  # This test case was supplied by Jacob Burckhardt:
1401	  cat >testcase06 <<EOF
1402g
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414i
1415EOF
1416
1417	  # This test is supposed to verify that the horizon lines are the same
1418	  # for both 2-way diffs, but unfortunately, it does not fail with the
1419	  # old version of cvs.  However, Karl Tomlinson still thought it would
1420	  # be good to test it anyway:
1421	  cat >testcase07 <<EOF
1422h
1423f
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433g
1434r
1435
1436
1437
1438i
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449i
1450EOF
1451
1452	  # This test case was supplied by Jacob Burckhardt:
1453	  cat >testcase08 <<EOF
1454Both changes move this line to the end of the file.
1455
1456no
1457changes
1458here
1459
1460First change will delete this line.
1461
1462First change will also delete this line.
1463
1464    no
1465    changes
1466    here
1467
1468Second change will change it here.
1469
1470        no
1471        changes
1472        here
1473EOF
1474
1475	  # This test case was supplied by Jacob Burckhardt.  Note that I do not
1476	  # think cvs has ever failed with this case, but I include it anyway,
1477	  # since I think it is a hard case.  It is hard because Peter Miller's
1478	  # fmerge utility fails on it:
1479	  cat >testcase09 <<EOF
1480m
1481a
1482{
1483}
1484b
1485{
1486}
1487EOF
1488
1489	  # This test case was supplied by Martin Dorey and simplified by Jacob
1490	  # Burckhardt:
1491	  cat >testcase10 <<EOF
1492
1493    petRpY ( MtatRk );
1494    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
1495
1496    MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
1497    OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
1498
1499    Bloke_GttpfIRte_MtpeaL ( &acI );
1500MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
1501{
1502    fV ( Y < 16 )
1503    {
1504        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1505                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
1506                                jfle_Uecopd_MfJe_fY_Mectopk,
1507                                nRVVep ) );
1508    }
1509    elke
1510    {
1511        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1512                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
1513                                jfle_Uecopd_MfJe_fY_Mectopk,
1514                                nRVVep ) );
1515    }
1516
1517}
1518
1519
1520/****************************************************************************
1521*                                                                           *
1522*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
1523*                                                                           *
1524****************************************************************************/
1525
1526MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
1527{
1528MTGTXM MtatRk = Zy;
1529
1530    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
1531
1532    petRpY ( MtatRk );
1533
1534}
1535    HfkQipfte ( waYdle,                 /*  waYdle                         */
1536                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
1537                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
1538                0,                      /*  MRrepVlRoRk KfxoYfkL           */
1539                beYgtz                  /*  nEtek to Apfte                 */
1540              );
1541
1542    petRpY ( Zy );
1543}
1544EOF
1545}
1546
1547# Create "your" revisions for diffmerge1
1548diffmerge_create_your_files() {
1549	  # remove the Button() method
1550	  cat >testcase01 <<\EOF
1551// Button.java
1552
1553package random.application;
1554
1555import random.util.*;
1556
1557public class Button
1558{
1559  /* Instantiates a Button with origin (0, 0) and zero width and height.
1560   * You must call an initializer method to properly initialize the Button.
1561   */
1562  public Button ()
1563  {
1564    super ();
1565
1566    _titleColor = Color.black;
1567    _disabledTitleColor = Color.gray;
1568    _titleFont = Font.defaultFont ();
1569  }
1570}
1571EOF
1572
1573	  cat >testcase02 <<\EOF
1574y
1575a
1576a
1577a
1578a
1579EOF
1580
1581	  cat >testcase03 <<\EOF
1582x
1583s
1584a
1585b
1586s
1587b
1588s
1589y
1590EOF
1591
1592	  cat >testcase04 <<\EOF
1593s
1594m
1595s
1596v
1597s
1598m
1599s
1600EOF
1601
1602	  cat >testcase05 <<\EOF
1603v
1604s
1605m
1606s
1607s
1608s
1609s
1610s
1611s
1612s
1613s
1614s
1615s
1616v
1617EOF
1618
1619	  # Test case 6 and test case 7 both use the same input files, but they
1620	  # order the input files differently.  In one case, a certain file is
1621	  # used as the older file, but in the other test case, that same file
1622	  # is used as the file which has changes.  I could have put echo
1623	  # commands here, but since the echo lines would be the same as those
1624	  # in the previous function, I decided to save space and avoid repeating
1625	  # several lines of code.  Instead, I merely swap the files:
1626	  mv testcase07 tmp
1627	  mv testcase06 testcase07
1628	  mv tmp testcase06
1629
1630	  # Make the date newer so that cvs thinks that the files are changed:
1631	  touch testcase06 testcase07
1632
1633	  cat >testcase08 <<\EOF
1634no
1635changes
1636here
1637
1638First change has now added this in.
1639
1640    no
1641    changes
1642    here
1643
1644Second change will change it here.
1645
1646        no
1647        changes
1648        here
1649
1650Both changes move this line to the end of the file.
1651EOF
1652
1653	  cat >testcase09 <<\EOF
1654
1655m
1656a
1657{
1658}
1659b
1660{
1661}
1662c
1663{
1664}
1665EOF
1666
1667	  cat >testcase10 <<\EOF
1668
1669    fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
1670
1671    petRpY ( MtatRk );
1672    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
1673
1674    fV ( jfle_Uecopd_KRLIep < 16 )
1675    {
1676        MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
1677    }
1678    elke
1679    {
1680        MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
1681        fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
1682
1683        MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
1684        OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
1685
1686    Bloke_GttpfIRte_MtpeaL ( &acI );
1687MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
1688{
1689MTGTXM MtatRk = Zy;
1690
1691    fV ( Y < 16 )
1692    {
1693        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1694                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
1695                                jfle_Uecopd_MfJe_fY_Mectopk,
1696                                nRVVep ) );
1697    }
1698    elke
1699    {
1700        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1701                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
1702                                jfle_Uecopd_MfJe_fY_Mectopk,
1703                                nRVVep ) );
1704    }
1705
1706    petRpY ( MtatRk );
1707
1708}
1709
1710
1711/****************************************************************************
1712*                                                                           *
1713*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
1714*                                                                           *
1715****************************************************************************/
1716
1717MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
1718{
1719MTGTXM MtatRk = Zy;
1720
1721    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
1722
1723    petRpY ( MtatRk );
1724
1725}
1726    HfkQipfte ( waYdle,                 /*  waYdle                         */
1727                waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
1728                (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
1729                0,                      /*  MRrepVlRoRk KfxoYfkL           */
1730                beYgtz                  /*  nEtek to Apfte                 */
1731              );
1732
1733    petRpY ( Zy );
1734}
1735
1736EOF
1737}
1738
1739# Create "my" revisions for diffmerge1
1740diffmerge_create_my_files() {
1741          # My working copy still has the Button() method, but I
1742	  # comment out some code at the top of the class.
1743	  cat >testcase01 <<\EOF
1744// Button.java
1745
1746package random.application;
1747
1748import random.util.*;
1749
1750public class Button
1751{
1752  /* Instantiates a Button with origin (0, 0) and zero width and height.
1753   * You must call an initializer method to properly initialize the Button.
1754   */
1755  public Button ()
1756  {
1757    super ();
1758
1759    // _titleColor = Color.black;
1760    // _disabledTitleColor = Color.gray;
1761    // _titleFont = Font.defaultFont ();
1762  }
1763
1764  /* Convenience constructor for instantiating a Button with
1765   * bounds x, y, width, and height.  Equivalent to
1766   *     foo = new Button ();
1767   *     foo.init (x, y, width, height);
1768   */
1769  public Button (int x, int y, int width, int height)
1770  {
1771    this ();
1772    init (x, y, width, height);
1773  }
1774}
1775EOF
1776
1777	  cat >testcase02 <<\EOF
1778a
1779a
1780a
1781a
1782m
1783EOF
1784
1785	  cat >testcase03 <<\EOF
1786x
1787s
1788c
1789s
1790b
1791s
1792y
1793EOF
1794
1795	  cat >testcase04 <<\EOF
1796v
1797s
1798x
1799m
1800m
1801x
1802s
1803v
1804s
1805x
1806m
1807m
1808x
1809s
1810v
1811EOF
1812
1813	  # Note that in test case 5, there are no changes in the "mine"
1814	  # section, which explains why there is no command here which writes to
1815	  # file testcase05.
1816
1817	  # no changes for testcase06
1818
1819	  # The two branches make the same changes:
1820	  cp ../yours/testcase07 .
1821
1822	  cat >testcase08 <<\EOF
1823no
1824changes
1825here
1826
1827First change will delete this line.
1828
1829First change will also delete this line.
1830
1831    no
1832    changes
1833    here
1834
1835Second change has now changed it here.
1836
1837        no
1838        changes
1839        here
1840
1841Both changes move this line to the end of the file.
1842EOF
1843
1844	  cat >testcase09 <<\EOF
1845m
1846a
1847{
1848}
1849b
1850{
1851}
1852c
1853{
1854}
1855EOF
1856
1857	  cat >testcase10 <<\EOF
1858
1859    petRpY ( MtatRk );
1860    fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
1861
1862    MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
1863    OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
1864
1865    Bloke_GttpfIRte_MtpeaL ( &acI );
1866MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
1867{
1868    fV ( Y < 16 )
1869    {
1870        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1871                                                      Y * jfle_Uecopd_MfJe_fY_Mectopk,
1872                                jfle_Uecopd_MfJe_fY_Mectopk,
1873                                nRVVep ) );
1874    }
1875    elke
1876    {
1877        petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1878                                                 ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
1879                                jfle_Uecopd_MfJe_fY_Mectopk,
1880                                nRVVep ) );
1881    }
1882
1883}
1884
1885
1886/****************************************************************************
1887*                                                                           *
1888*   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
1889*                                                                           *
1890****************************************************************************/
1891
1892MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
1893{
1894MTGTXM MtatRk = Zy;
1895
1896    MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
1897
1898    petRpY ( MtatRk );
1899
1900}
1901    HfkQipfte ( waYdle,                 /*  waYdle…

Large files files are truncated, but you can click here to view the full file