Merge branch 'mirbsd'
[alioth/cvs.git] / src / sanity.sh
1 #! /bin/sh
2 :
3 # set DISABLE_ANY_RSH=1 to skip rsh and ssh calls
4 #
5 #       sanity.sh -- a growing testsuite for cvs.
6 #
7 # The copyright notice said: "Copyright (C) 1992, 1993 Cygnus Support"
8 # I'm not adding new copyright notices for new years as our recent 
9 # practice has been to include copying terms without copyright notices.
10 #
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2, or (at your option)
14 # any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20 #
21 # Original Author: K. Richard Pixley
22
23 # usage:
24 usage ()
25 {
26     echo "Usage: `basename $0` --help"
27     echo "Usage: `basename $0` [--eklr] [-c CONFIG-FILE] [-f FROM-TEST] \\"
28     echo "                 [-h HOSTNAME] [-s CVS-FOR-CVS-SERVER] CVS-TO-TEST \\"
29     echo "                 [TESTS-TO-RUN...]"
30 }
31
32 exit_usage ()
33 {
34     usage 1>&2
35     exit 2
36 }
37
38 exit_help ()
39 {
40     usage
41     echo
42     echo "-H|--help     display this text"
43     echo "-c CONFIG-FILE"
44     echo "--config=CONFIG_FILE"
45     echo "              use an alternate test suite config file (defaults to"
46     echo "              \`sanity.config.sh' in the same directory as"
47     echo "              CVS-TO-TEST is found in)"
48     echo "-e|--skipfail Treat tests that would otherwise be nonfatally skipped"
49     echo "              for reasons like missing tools as failures, exiting"
50     echo "              with an error message.  Also treat warnings as"
51     echo "              failures."
52     echo "-f FROM-TEST"
53     echo "--from-test=FROM-TEST"
54     echo "              run TESTS-TO-RUN, skipping all tests in the list before"
55     echo "              FROM-TEST"
56     echo "-h HOSTNAME"
57     echo "--hostname HOSTNAME"
58     echo "              Use :ext:HOSTNAME to run remote tests rather than"
59     echo "              :fork:.  Implies --remote and assumes that \$TESTDIR"
60     echo "              resolves to the same directory on both the client and"
61     echo "              the server."
62     echo "-k|--keep     try to keep directories created by individual tests"
63     echo "              around, exiting after the first test which supports"
64     echo "              --keep"
65     echo "-l|--link-root"
66     echo "              test CVS using a symlink to a real CVSROOT"
67     echo "-n|--noredirect"
68     echo "              test a secondary/primary CVS server (writeproxy)"
69     echo "              configuration with the Redirect response disabled"
70     echo "              (implies --proxy)."
71     echo "-p|--proxy    test a secondary/primary CVS server (writeproxy)"
72     echo "              configuration (implies --remote)."
73     echo "-r|--remote   test client/server, as opposed to local, CVS"
74     echo "-s CVS-FOR-CVS-SERVER"
75     echo "--server=CVS-FOR-CVS-SERVER"
76     echo "              use CVS-FOR-CVS-SERVER as the path to the CVS SERVER"
77     echo "              executable to be tested (defaults to CVS-TO-TEST and"
78     echo "              implies --remote)"
79     echo
80     echo "CVS-TO-TEST   the path to the CVS executable to be tested; used as"
81     echo "              the path to the CVS client when CVS-FOR-CVS-SERVER is"
82     echo "              specified"
83     echo "TESTS-TO-RUN  the names of the tests to run (defaults to all tests)"
84     exit 2
85 }
86
87 checklongoptarg()
88 {
89     if test "x$1" != xoptional && test -z "$OPTARG"; then
90         echo "option \`--$LONGOPT' requires an argument" >&2
91         exit_usage
92     fi
93 }
94
95 # See TODO list at end of file.
96
97 # required to make this script work properly.
98 unset CVSREAD
99
100 # We want to invoke a predictable set of i18n behaviors, not whatever
101 # the user running this script might have set.
102 # In particular:
103 #   'sort' and tabs and spaces (LC_COLLATE).
104 #   Messages from getopt (LC_MESSAGES) (in the future, CVS itself might 
105 #     also alter its messages based on LC_MESSAGES).
106 LANG=C
107 export LANG
108 LC_ALL=C
109 export LC_ALL
110
111 # And a few tests want a predictable umask.
112 umask 0002
113
114 #
115 # Initialize the test counts.
116 #
117 passed=0
118 skipped=0
119 warnings=0
120
121
122
123 #
124 # read our options
125 #
126 unset configfile
127 unset fromtest
128 unset remotehost
129 unset rootoptions
130 keep=false
131 linkroot=false
132 noredirect=false
133 proxy=false
134 remote=false
135 servercvs=false
136 skipfail=false
137 while getopts Hc:ef:h:klnprs:-: option ; do
138     # convert the long opts to short opts
139     if test x$option = x-;  then
140         # remove any argument
141         if echo "$OPTARG" |grep = >/dev/null; then
142             LONGOPT=`echo "$OPTARG" |sed 's/=.*$//'`
143             OPTARG=`echo "$OPTARG" |sed -e 's/^.*=//'`
144         else
145             LONGOPT=$OPTARG
146             OPTARG=
147         fi
148         # Convert LONGOPT to lower case
149         LONGOPT=`echo "$LONGOPT" |sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'`
150         case "$LONGOPT" in
151             c|co|con|conf|confi|config)
152                 option=c
153                 checklongoptarg
154                 ;;
155             f|fr|fro|from|from-|from-t|from-te|from-tes|from-test)
156                 option=f
157                 checklongoptarg
158                 ;;
159             h)
160                 echo "\`--h' is ambiguous.  Could mean \`--help' or \`--hostname'" >&2
161                 exit_usage
162                 ;;
163             he|hel|help)
164                 option=H
165                 OPTARG=
166                 ;;
167             ho|hos|host|hostn|hostna|hostnam|hostname)
168                 option=h
169                 checklongoptarg
170                 ;;
171             k|ke|kee|keep)
172                 option=k
173                 OPTARG=
174                 ;;
175             l|li|lin|link|link-|link-r]|link-ro|link-roo|link-root)
176                 option=l
177                 OPTARG=
178                 ;;
179             n|no|nor|nore|nored|noredi|noredir|noredire|noredirec|noredirect)
180                 option=n
181                 OPTARG=
182                 ;;
183             p|pr|pro|prox|proxy)
184                 option=p
185                 OPTARG=
186                 ;;
187             r|re|rem|remo|remot|remote)
188                 option=r
189                 OPTARG=
190                 ;;
191             s)
192                 echo "\`--s' is ambiguous.  Could mean \`--server' or \`--skipfail'" >&2
193                 exit_usage
194                 ;;
195             se|ser|serv|serve|server)
196                 option=s
197                 checklongoptarg
198                 ;;
199             sk|ski|skip|skipf|skipfa|skipfai|skipfail)
200                 option=e
201                 OPTARG=
202                 ;;
203             *)
204                 option=\?
205                 OPTARG=
206         esac
207     fi
208     case "$option" in
209         c)
210             configfile="$OPTARG"
211             ;;
212         e)
213             skipfail=:
214             ;;
215         f)
216             fromtest="$OPTARG"
217             ;;
218         h)
219             # Set a remotehost to run the remote tests on via :ext:
220             # Implies `-r' and assumes that $TESTDIR resolves to the same
221             # directory on the client and the server.
222             remotehost="$OPTARG"
223             remote=:
224             ;;
225         H)
226             exit_help
227             ;;
228         k)
229             # The -k (keep) option will eventually cause all the tests to
230             # leave around the contents of the /tmp directory; right now only
231             # some implement it.  Not originally intended to be useful with
232             # more than one test, but this should work if each test uses a
233             # uniquely named dir (use the name of the test).
234             keep=:
235             ;;
236         l)
237             linkroot=:
238             ;;
239         n)
240             proxy=:
241             noredirect=:
242             remote=:
243             ;;
244         p)
245             proxy=:
246             remote=:
247             ;;
248         r)
249             remote=:
250             ;;
251         s)
252             servercvs="$OPTARG"
253             remote=:
254             ;;
255         \?)
256             exit_usage
257             ;;
258     esac
259 done
260
261 # boot the arguments we used above
262 while test $OPTIND -gt 1 ; do
263     shift
264     OPTIND=`expr $OPTIND - 1`
265 done
266
267 # Use full path for CVS executable, so that CVS_SERVER gets set properly
268 # for remote.
269 case $1 in
270 "")
271   exit_usage
272   ;;
273 /*)
274   testcvs=$1
275   ;;
276 *)
277   testcvs=`pwd`/$1
278   ;;
279 esac
280 shift
281
282 # Verify that $testcvs looks like CVS.
283 # we can't use test -x since BSD 4.3 doesn't support it.
284 if test ! -f $testcvs || test ! -r $testcvs; then
285   echo "No such file or file not readable: $testcvs" >&2
286   exit 1
287 fi
288 if $testcvs --version </dev/null 2>/dev/null |
289      grep '^Concurrent Versions System' >/dev/null 2>&1; then :; else
290   echo "Not a CVS executable: $testcvs" >&2
291   exit 1
292 fi
293
294 # If $remotehost is set, warn if $TESTDIR isn't since we are pretty sure
295 # that its default value of `/tmp/cvs-sanity' will not resolve to the same
296 # directory on two different machines.
297 if test -n "$remotehost" && test -z "$TESTDIR"; then
298     echo "WARNING: CVS server hostname is set and \$TESTDIR is not.  If" >&2
299     echo "$remotehost is not the local machine, then it is unlikely that" >&2
300     echo "the default value assigned to \$TESTDIR will resolve to the same" >&2
301     echo "directory on both this client and the CVS server." >&2
302 fi
303
304 # Read our config file if we can find it.
305 #
306 # The config file should always be located in the same directory as the CVS
307 # executable, unless we are testing an executable outside of the build
308 # directory.  In this case, we echo a warning and attempt to assume the most
309 # portable configuration.
310 if test -z "$configfile"; then
311         configfile=`dirname $testcvs`/sanity.config.sh
312 fi
313 if test -r "$configfile"; then
314         . "$configfile"
315 else
316         echo "WARNING: Failed to locate test suite config file" >&2
317         echo "         \`$configfile'." >&2
318 fi
319
320
321
322 # Set a default value for $CVS_RSH. The sanity.config.sh file will
323 # have the configured value in the RSH_DFLT variable.
324 #
325 : ${CVS_RSH=${RSH_DFLT:-ssh}}; export CVS_RSH
326
327 if test -n "$remotehost"; then
328     # Verify that $CVS_RSH $remotehost works.
329     result=`$CVS_RSH $remotehost 'echo test'`
330     if test $? != 0 || test "x$result" != "xtest"; then
331         echo "\`$CVS_RSH $remotehost' failed." >&2
332         exit 1
333     fi
334 fi
335
336 case "$servercvs" in
337 "")
338   exit_usage
339   ;;
340 false)
341   ;;
342 /*)
343   ;;
344 *)
345   servercvs=`pwd`/$servercvs
346   ;;
347 esac
348
349 if test false != $servercvs; then
350   # Allow command line to override $CVS_SERVER
351   CVS_SERVER=$servercvs
352 else
353   # default $CVS_SERVER to ${testcvs}
354   : ${CVS_SERVER=$testcvs}
355   # With the previous command, effectively defaults $servercvs to $CVS_SERVER,
356   # then $testcvs
357   servercvs=$CVS_SERVER
358 fi
359 export CVS_SERVER
360 servercvs_orig=$servercvs
361
362 # Fail in client/server mode if our ${servercvs} does not contain server
363 # support.
364 if $remote; then
365   if test -n "$remotehost"; then
366     if $CVS_RSH $remotehost "test ! -f ${servercvs} || test ! -r ${servercvs}"
367     then
368       echo "No such file or file not readable: $remotehost:${testcvs}" >&2
369       exit 1
370     fi
371     if $CVS_RSH $remotehost "${servercvs} --version </dev/null 2>/dev/null |
372          grep '^Concurrent Versions System' >/dev/null 2>&1"; then :; else
373       echo "Not a CVS executable: $remotehost:${servercvs}" >&2
374       exit 1
375     fi
376     if $CVS_RSH $remotehost "${servercvs} --version </dev/null |
377          grep '^Concurrent.*(.*server)$' >/dev/null 2>&1"; then :; else
378       echo "CVS executable \`$remotehost:${servercvs}' does not contain server support." >&2
379       exit 1
380     fi
381   else
382     if test ! -f ${servercvs} || test ! -r ${servercvs}; then
383       echo "No such file or file not readable: ${testcvs}" >&2
384       exit 1
385     fi
386     if ${servercvs} --version </dev/null 2>/dev/null |
387          grep '^Concurrent Versions System' >/dev/null 2>&1; then :; else
388       echo "Not a CVS executable: ${servercvs}" >&2
389       exit 1
390     fi
391     if ${servercvs} --version </dev/null |
392          grep '^Concurrent.*(.*server)$' >/dev/null 2>&1; then :; else
393       echo "CVS executable \`${servercvs}' does not contain server support." >&2
394       exit 1
395     fi
396   fi
397 fi
398
399 # Fail in client/server mode if our ${testcvs} does not contain client
400 # support.
401 if $remote; then
402   if ${testcvs} --version </dev/null |
403        grep '^Concurrent.*(client.*)$' >/dev/null 2>&1; then :; else
404     echo "CVS executable \`${testcvs}' does not contain client support." >&2
405     exit 1
406   fi
407 fi
408
409 # For the "fork" tests.
410 if ${testcvs} --version </dev/null |
411      grep '^Concurrent.*(.*server)$' >/dev/null 2>&1
412 then
413   testcvs_server_support=:
414 else
415   testcvs_server_support=false
416 fi
417
418
419
420 dokeep() 
421
422     if ${keep}; then
423       echo "Keeping ${TESTDIR} for test case \`${what}' and exiting due to --keep"
424       exit 0
425     fi
426 }
427
428
429
430 ###
431 ### GUTS
432 ###
433
434 # "debugger"
435 #set -x
436
437 echo 'This test should produce no other output than this message, and a final "OK".'
438 echo '(Note that the test can take an hour or more to run and periodically stops'
439 echo 'for as long as one minute.  Do not assume there is a problem just because'
440 echo 'nothing seems to happen for a long time.  If you cannot live without'
441 echo "running status, try the command: \`tail -f check.log' from another window.)"
442
443 # Regexp to match what the CVS client will call itself in output that it prints.
444 # FIXME: we don't properly quote this--if the name contains . we'll
445 # just spuriously match a few things; if the name contains other regexp
446 # special characters we are probably in big trouble.
447 CPROG=`basename ${testcvs} |sed 's/\.exe$//'`
448 # And the regexp for the CVS server when we have one.  In local mode, this
449 # defaults to $CPROG since $servercvs already did.
450 # FIXCVS: There are a few places in error messages where CVS suggests a command
451 # and outputs $SPROG as the suggested executable.  This could hopefully use
452 # MT (tagged text - see doc/cvs-client.texi) to request that the client print
453 # its own name.
454 SPROG=`basename ${servercvs} |sed 's/\.exe$//'`
455
456
457 # Match the hostname
458 hostname="[-_.a-zA-Z0-9]*"
459
460 # Regexp to match a commitid
461 commitid="[a-zA-Z0-9]*"
462
463 # Regexp to match the name of a temporary file (from cvs_temp_name).
464 # This appears in certain diff output.
465 tempfile="cvs[-a-zA-Z0-9.%_]*"
466 # $tempname set after $TMPDIR, below.
467
468 # Regexp to match a date in RFC822 format (as amended by RFC1123).
469 RFCDATE="[a-zA-Z0-9 ][a-zA-Z0-9 ]* [0-9:][0-9:]* -0000"
470 RFCDATE_EPOCH="1 Jan 1970 00:00:00 -0000"
471
472 # Special times used in touch -t commands and the regular expresions
473 # to match them. Now that the tests set TZ=UTC0, it
474 # should be easier to be more exact in their regexp.
475 TOUCH1971="197107040343"
476 # This date regexp was 1971/07/0[3-5] [0-9][0-9]:43:[0-9][0-9]
477 ISO8601DATE1971="1971-07-04 03:43:[0-9][0-9] [+-]0000"
478
479 TOUCH2034="203412251801"
480 # This date regexp was 2034/12/2[4-6] [0-9][0-9]:01:[0-9][0-9]
481 ISO8601DATE2034="2034-12-25 18:01:[0-9][0-9] [+-]0000"
482
483 # Used in admin tests for exporting RCS files.
484 # The RAWRCSDATE..... format is for internal ,v files and
485 # the ISO8601DATE..... format is to allow for a regular expression in
486 # 'cvs log' output patterns. The tests that use this set of specific
487 # ${ISO8601DATE.....} variables also force TZ=UTC0 for the test.
488 RAWRCSDATE2000A="2000.11.24.15.58.37"
489 RAWRCSDATE1996A="96.11.24.15.57.41"
490 RAWRCSDATE1996B="96.11.24.15.56.05"
491 ISO8601DATE2000A="2000-11-24 15:58:37 [+-]0000"
492 ISO8601DATE1996A="1996-11-24 15:57:41 [+-]0000"
493 ISO8601DATE1996B="1996-11-24 15:56:05 [+-]0000"
494
495 # Regexp to match the date in cvs log command output
496 # This format has been enhanced in the future to accept either
497 # old-style cvs log output dates or new-style ISO8601 timezone
498 # information similar to the ISODATE format. The RCSKEYDATE is
499 # similar, but uses '/' instead of '-' to sepearate year/month/day
500 # and does not include the optional timezone offset.
501 ISO8601DATE="[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-6][0-9]:[0-6][0-9] [-+][0-1][0-9][0-6][0-9]"
502
503 # Regexp to match the dates found in rcs keyword strings
504 RCSKEYDATE="[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]"
505
506 # Regexp to match the date in the delta section of rcs format files.
507 # Dates in very old RCS files may not have included the century.
508 RCSDELTADATE="[0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]"
509
510 # Regexp to match a date in standard Unix format as used by rdiff
511 # FIXCVS: There's no reason for rdiff to use a different date format
512 # than diff does
513 DATE="[a-zA-Z]* [a-zA-Z]* [ 1-3][0-9] [0-9:]* [0-9]*"
514 # ISO 8601 format "yyyy-mm-dd hh:mm -0000"
515 ISODATE="[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9] [+-][0-9][0-9][0-9][0-9]"
516 # %p format is not well defined (nil) and hex digits are common. Using
517 # ..* is a bad idea as the tests take a very long time to run due to
518 # the complexity of the expressions.  If you run into any other characters
519 # that are used in a %p format, add them here.
520 PFMT="[0-9a-zA-Z()][0-9a-zA-Z()]*"
521
522 # Which directories should Which and find_tool search for executables?
523 SEARCHPATH=$PATH:/usr/local/bin:/usr/contrib/bin:/usr/contrib:/usr/gnu/bin:/local/bin:/local/gnu/bin:/gnu/bin:/sw/bin:/usr/pkg/bin
524
525 # Do not assume that `type -p cmd` is portable
526 # Usage: Which [-a] [-x|-f|-r] prog [$SEARCHPATH:/with/directories:/to/search]
527 Which() {
528   # Optional first argument for file type, defaults to -x.
529   # Second argument is the file or directory to be found.
530   # Third argument is the PATH to search.
531   # By default, print only the first file that matches,
532   # -a will cause all matches to be printed.
533   notevery=:
534   if [ "x$1" = "x-a" ]; then notevery=false; shift; fi
535   case "$1" in
536     -*) t=$1; shift ;;
537     *) t=-x ;;
538   esac
539   case "$1" in
540     # FIXME: Someday this may need to be fixed
541     # to deal better with C:\some\path\to\ssh values...
542     /*) test $t $1 && echo $1 ;;
543     *) for d in `IFS=:; echo ${2-$SEARCHPATH}`
544        do
545          test $t $d/$1 && { echo $d/$1; if $notevery; then break; fi; }
546        done
547        ;;
548   esac
549 }
550
551
552 # On cygwin32, we may not have /bin/sh.
553 if test -r /bin/sh; then
554   TESTSHELL="/bin/sh"
555 else
556   TESTSHELL=`Which -f sh`
557   if test ! -r "$TESTSHELL"; then
558     TESTSHELL="/bin/sh"
559   fi
560 fi
561
562 # FIXME: try things (what things? checkins?) without -m.
563 #
564 # Some of these tests are written to expect -Q.  But testing with
565 # -Q is kind of bogus, it is not the way users actually use CVS (usually).
566 # So new tests probably should invoke ${testcvs} directly, rather than ${CVS}.
567 # and then they've obviously got to do something with the output....
568 #
569 CVS="${testcvs} -Q"
570
571 LOGFILE=`pwd`/check.log
572
573 # Save the previous log in case the person running the tests decides
574 # they want to look at it.  The extension ".plog" is chosen for consistency
575 # with dejagnu.
576 test -f check.plog && mv check.plog check.plog~
577 test -f check.log && mv check.log check.plog
578
579 # Create the log file so check.log can be tailed almost immediately after
580 # this script is started.  Otherwise it can take up to a minute or two before
581 # the log file gets created when $remotehost is specified on some systems,
582 # which makes for a lot of failed `tail -f' attempts.
583 touch check.log
584
585 # Workaround any X11Forwarding by ssh. Otherwise this text:
586 #   Warning: No xauth data; using fake authentication data for X11 forwarding.
587 # has been known to end up in the test results below
588 # causing the test to fail.
589 [ -n "$DISPLAY" ] && unset DISPLAY
590   
591 # The default value of /tmp/cvs-sanity for TESTDIR is dubious,
592 # because it loses if two people/scripts try to run the tests
593 # at the same time.  Some possible solutions:
594 # 1.  Use /tmp/cvs-test$$.  One disadvantage is that the old
595 #     cvs-test* directories would pile up, because they wouldn't
596 #     necessarily get removed.
597 # 2.  Have everyone/everything running the testsuite set
598 #     TESTDIR to some appropriate directory.
599 # 3.  Have the default value of TESTDIR be some variation of
600 #     `pwd`/cvs-sanity.  The biggest problem here is that we have
601 #     been fairly careful to test that CVS prints in messages the
602 #     actual pathnames that we pass to it, rather than a different
603 #     pathname for the same directory, as may come out of `pwd`.
604 #     So this would be lost if everything was `pwd`-based.  I suppose
605 #     if we wanted to get baroque we could start making symlinks
606 #     to ensure the two are different.
607 if test -n "$remotehost"; then
608         # We need to set $tmp on the server since $TMPDIR is compared against
609         # messages generated by the server.
610         tmp=`$CVS_RSH $remotehost 'cd /tmp; /bin/pwd || pwd' 2>/dev/null`
611         if test $? != 0; then
612             echo "$CVS_RSH $remotehost failed." >&2
613             exit 1
614         fi
615 else
616         tmp=`(cd /tmp; /bin/pwd || pwd) 2>/dev/null`
617 fi
618
619 # Now:
620 #       1) Set TESTDIR if it's not set already
621 #       2) Remove any old test remnants
622 #       3) Create $TESTDIR
623 #       4) Normalize TESTDIR with `cd && (/bin/pwd || pwd)`
624 #          (This will match CVS output later)
625 : ${TESTDIR=$tmp/cvs-sanity}
626 # clean any old remnants (we need the chmod because some tests make
627 # directories read-only)
628 if test -d $TESTDIR; then
629     chmod -R a+wx $TESTDIR
630     rm -rf $TESTDIR
631 fi
632 # These exits are important.  The first time I tried this, if the `mkdir && cd`
633 # failed then the build directory would get blown away.  Some people probably
634 # wouldn't appreciate that.
635 mkdir $TESTDIR || exit 1
636 cd $TESTDIR || exit 1
637 # Ensure $TESTDIR is absolute
638 if echo "$TESTDIR" |grep '^[^/]'; then
639     # Don't resolve this unless we have to.  This keeps symlinks intact.  This
640     # is important at least when testing using -h $remotehost, because the same
641     # value for $TESTDIR must resolve to the same directory on the client and
642     # the server and we likely used Samba, and possibly symlinks, to do this.
643     TESTDIR=`(/bin/pwd || pwd) 2>/dev/null`
644 fi
645
646 if test -z "$TESTDIR" || echo "$TESTDIR" |grep '^[^/]'; then
647     echo "Unable to resolve TESTDIR to an absolute directory." >&2
648     exit 1
649 fi
650 cd $TESTDIR
651
652
653
654 : ${TIMING=false}
655 if $remote; then
656     # Now override our CVS_RSH in order to forward variables which affect the
657     # test suite through.  This always needs to be done when $remotehost is
658     # set, needs to be done in $proxy mode for the crerepos tests, and needs to
659     # be done in $remote mode for the writeproxy-ssh tests.
660     if $TIMING; then
661         time="/usr/bin/time -ao'$TESTDIR/time.out'"
662     else
663         time=
664     fi
665     cat >$TESTDIR/ssh-wrapper-env <<EOF
666 #! $TESTSHELL
667 while [ \$# -gt 0 ]
668 do
669   case "\$1" in
670     *=*)
671       eval "\$1"
672       var=\`echo "\$1" | sed 's/^\\(.*\\)=.*\$/\\1/'\`
673       export \$var
674       ;;
675     *) break;;
676   esac
677   shift
678 done
679 exec \${1+"\$@"}
680 EOF
681     chmod a+x $TESTDIR/ssh-wrapper-env
682     cat >$TESTDIR/ssh-wrapper <<EOF
683 #! $TESTSHELL
684 hostname=\$1
685 shift
686 exec \
687 $CVS_RSH \
688          \$hostname \
689          $TESTDIR/ssh-wrapper-env \
690          "CVS_SERVER='\$CVS_SERVER'" \
691          "CVS_SERVER_SLEEP='\$CVS_SERVER_SLEEP'" \
692          "CVS_PARENT_SERVER_SLEEP='\$CVS_PARENT_SERVER_SLEEP'" \
693          "CVS_SERVER_LOG='\$CVS_SERVER_LOG'" \
694          "CVS_SECONDARY_LOG='\$CVS_SECONDARY_LOG'" \
695          "TMPDIR='\$TMPDIR'" \
696          "CVS_RSH='$TESTDIR/ssh-wrapper'" \
697          "CVSUMASK='\$CVSUMASK'" \
698          "CVS_PID='\$CVS_PID'" \
699          $time \
700          \${1+"\$@"}
701 EOF
702     chmod a+x $TESTDIR/ssh-wrapper
703     CVS_RSH=$TESTDIR/ssh-wrapper
704 fi # $remotehost
705
706
707
708 # Now set $TMPDIR if the user hasn't overridden it.
709 #
710 # We use a $TMPDIR under $TESTDIR by default so that two tests may be run at
711 # the same time without bumping heads without requiring the user to specify
712 # more than $TESTDIR.  See the test for leftover cvs-serv* directories near the
713 # end of this script at the end of "The big loop".
714 : ${TMPDIR=$TESTDIR/tmp}
715 export TMPDIR
716 if test -d $TMPDIR; then :; else
717     mkdir $TMPDIR
718 fi
719
720
721 # Regexp to match the the full path to a temporary file (from cvs_temp_name).
722 # This appears in certain diff output.
723 tempname=$TMPDIR/$tempfile
724
725 # Make sure various tools work the way we expect, or try to find
726 # versions that do.
727 : ${AWK=awk}
728 : ${EXPR=expr}
729 : ${ID=id}
730 : ${TR=tr}
731
732 # Keep track of tools that are found, but do NOT work as we hope
733 # in order to avoid them in future
734 badtools=
735 set_bad_tool ()
736 {
737    badtools=$badtools:$1
738 }
739 is_bad_tool ()
740 {
741    case ":$badtools:" in *:$1:*) return 0 ;; *) return 1 ; esac
742 }
743
744 version_test ()
745 {
746   vercmd=$1
747   verbad=:
748   if RES=`$vercmd --version </dev/null 2>&1`; then
749     if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
750       echo "$RES"
751       verbad=false
752     fi
753   fi
754   if $verbad; then
755     echo "The command \`$vercmd' does not support the --version option."
756   fi
757   # It does not really matter that --version is not supported
758   return 0
759 }
760
761 # Try to find a tool that satisfies all of the tests.
762 # Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
763 # Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
764 find_tool ()
765 {
766   default_TOOL=$1
767   echo find_tool: ${1+"$@"} >>$LOGFILE
768   cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
769   if test -z "$tooltests"; then tooltests=version_test; fi
770   clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
771   # Make sure the default tool is just the first real command name
772   for default_TOOL in $clist `IFS=:; echo $default_TOOL`; do break; done
773   TOOL=""
774   for trytool in $clist ; do
775     pass=:
776     for tooltest in $tooltests; do
777       result=`eval $tooltest $trytool`
778       rc=$?
779       echo "Running $tooltest $trytool" >>$LOGFILE
780       if test -n "$result"; then
781         echo "$result" >>$LOGFILE
782       fi
783       if test "$rc" = "0"; then
784         echo "PASS: $tooltest $trytool" >>$LOGFILE
785       elif test "$rc" = "77"; then
786         echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
787         TOOL=$trytool
788         pass=false
789       else
790         set_bad_tool $trytool
791         echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
792         pass=false
793       fi
794     done
795     if $pass; then
796       echo $trytool
797       return 0
798     fi
799   done
800   if test -n "$TOOL"; then
801     echo "Notice: The default version of \`$default_TOOL' is defective." >>$LOGFILE
802     echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
803     echo "Notice: The default version of \`$default_TOOL' is defective." >&2
804     echo "using \`$TOOL' and hoping for the best." >&2
805     echo $TOOL
806   else
807     echo $default_TOOL
808   fi
809 }  
810
811 id_tool_test ()
812 {
813   id=$1
814   if $id -u >/dev/null 2>&1 && $id -un >/dev/null 2>&1; then
815     return 0
816   else
817     echo "Running these tests requires an \`id' program that understands the"
818     echo "-u and -n flags.  Make sure that such an id (GNU, or many but not"
819     echo "all vendor-supplied versions) is in your path."
820     return 1
821   fi
822 }
823
824 ID=`find_tool id version_test id_tool_test`
825 echo "Using ID=$ID" >>$LOGFILE
826
827 # You can't run CVS as root; print a nice error message here instead
828 # of somewhere later, after making a mess.
829 for pass in false :; do
830   case "`$ID -u 2>/dev/null`" in
831     "0")
832       echo "Test suite does not work correctly when run as root" >&2
833       exit 1
834       ;;
835
836     *)
837       break
838       ;;
839   esac
840 done
841
842 # Cause NextStep 3.3 users to lose in a more graceful fashion.
843 expr_tooltest1 ()
844 {
845 expr=$1
846 if $expr 'abc
847 def' : 'abc
848 def' >/dev/null; then
849   # good, it works
850   return 0
851 else
852   echo 'Running these tests requires an "expr" program that can handle'
853   echo 'multi-line patterns.  Make sure that such an expr (GNU, or many but'
854   echo 'not all vendor-supplied versions) is in your path.'
855   return 1
856 fi
857 }
858
859 # Warn SunOS, SysVr3.2, etc., users that they may be partially losing
860 # if we can't find a GNU expr to ease their troubles...
861 expr_tooltest2 ()
862 {
863 expr=$1
864 if $expr 'a
865 b' : 'a
866 c' >/dev/null; then
867   echo 'Warning: you are using a version of expr that does not correctly'
868   echo 'match multi-line patterns.  Some tests may spuriously pass or fail.'
869   echo 'You may wish to make sure GNU expr is in your path.'
870   return 1
871 else
872   return 0
873 fi
874 }
875
876 expr_create_bar ()
877 {
878 echo 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >${TESTDIR}/foo
879 cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
880 cat ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar >${TESTDIR}/foo
881 cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
882 rm -f ${TESTDIR}/foo
883 }
884
885 expr_tooltest3 ()
886 {
887 expr=$1
888 # More SunOS lossage...
889 test ! -f ${TESTDIR}/bar && expr_create_bar
890 if $expr "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
891   : good, it works
892 else
893   echo 'Warning: you are using a version of expr that does not correctly'
894   echo 'match large patterns.  Some tests may spuriously pass or fail.'
895   echo 'You may wish to make sure GNU expr is in your path.'
896   return 1
897 fi
898 if $expr "`cat ${TESTDIR}/bar`x" : "`cat ${TESTDIR}/bar`y" >/dev/null; then
899   echo 'Warning: you are using a version of expr that does not correctly'
900   echo 'match large patterns.  Some tests may spuriously pass or fail.'
901   echo 'You may wish to make sure GNU expr is in your path.'
902   return 1
903 fi
904 # good, it works
905 return 0
906 }
907
908 # That we should have to do this is total bogosity, but GNU expr
909 # version 1.9.4-1.12 uses the emacs definition of "$" instead of the unix
910 # (e.g. SunOS 4.1.3 expr) one.  Rumor has it this will be fixed in the
911 # next release of GNU expr after 1.12 (but we still have to cater to the old
912 # ones for some time because they are in many linux distributions).
913 ENDANCHOR="$"
914 expr_set_ENDANCHOR ()
915 {
916 expr=$1
917 ENDANCHOR="$"
918 if $expr 'abc
919 def' : 'abc$' >/dev/null; then
920   ENDANCHOR='\'\'
921    echo "Notice: An ENDANCHOR of dollar does not work."
922    echo "Using a workaround for GNU expr versions 1.9.4 thru 1.12"
923 fi
924 return 0
925 }
926
927 # Work around another GNU expr (version 1.10-1.12) bug/incompatibility.
928 # "." doesn't appear to match a newline (it does with SunOS 4.1.3 expr).
929 # Note that the workaround is not a complete equivalent of .* because
930 # the first parenthesized expression in the regexp must match something
931 # in order for expr to return a successful exit status.
932 # Rumor has it this will be fixed in the
933 # next release of GNU expr after 1.12 (but we still have to cater to the old
934 # ones for some time because they are in many linux distributions).
935 DOTSTAR='.*'
936 expr_set_DOTSTAR ()
937 {
938 expr=$1
939 DOTSTAR='.*'
940 if $expr 'abc
941 def' : "a${DOTSTAR}f" >/dev/null; then
942   : good, it works
943 else
944   DOTSTAR='\(.\|
945 \)*'
946   echo "Notice: DOTSTAR changed from sane \`.*' value to \`$DOTSTAR\`"
947   echo "to workaround GNU expr version 1.10 thru 1.12 bug where \`.'"
948   echo "does not match a newline."
949 fi
950 return 0
951 }
952
953 # Now that we have DOTSTAR, make sure it works with big matches
954 expr_tooltest_DOTSTAR ()
955 {
956 expr=$1
957 test ! -f ${TESTDIR}/bar && expr_create_bar
958 if $expr "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; then
959   # good, it works
960   return 0
961 else
962   echo 'Warning: you are using a version of expr that does not correctly'
963   echo 'match large patterns.  Some tests may spuriously pass or fail.'
964   echo 'You may wish to make sure GNU expr is in your path.'
965   return 77
966 fi
967 }
968
969 EXPR=`find_tool ${EXPR}:gexpr \
970   version_test expr_tooltest1 expr_tooltest2 expr_tooltest3 \
971 expr_set_ENDANCHOR expr_set_DOTSTAR expr_tooltest_DOTSTAR`
972
973 # Set the ENDANCHOR and DOTSTAR for the chosen expr version.
974 expr_set_ENDANCHOR ${EXPR} >/dev/null
975 expr_tooltest_DOTSTAR ${EXPR} >/dev/null
976
977 echo "Using EXPR=$EXPR" >>$LOGFILE
978 echo "Using ENDANCHOR=$ENDANCHOR" >>$LOGFILE
979 echo "Using DOTSTAR=$DOTSTAR" >>$LOGFILE
980
981 # Cleanup
982 rm -f ${TESTDIR}/bar
983
984 # Work around yet another GNU expr (version 1.10) bug/incompatibility.
985 # "+" is a special character, yet for unix expr (e.g. SunOS 4.1.3)
986 # it is not.  I doubt that POSIX allows us to use \+ and assume it means
987 # (non-special) +, so here is another workaround
988 # Rumor has it this will be fixed in the
989 # next release of GNU expr after 1.12 (but we still have to cater to the old
990 # ones for some time because they are in many linux distributions).
991 PLUS='+'
992 if $EXPR 'a +b' : "a ${PLUS}b" >/dev/null; then
993   : good, it works
994 else
995   PLUS='\+'
996 fi
997
998 # Likewise, for ?
999 QUESTION='?'
1000 if $EXPR 'a?b' : "a${QUESTION}b" >/dev/null; then
1001   : good, it works
1002 else
1003   QUESTION='\?'
1004 fi
1005
1006 # Now test the username to make sure it contains only valid characters
1007 username=`$ID -un`
1008 if $EXPR "${username}" : "${username}" >/dev/null; then
1009   : good, it works
1010 else
1011   echo "Test suite does not work correctly when run by a username" >&2
1012   echo "containing regular expression meta-characters." >&2
1013   exit 1
1014 fi
1015
1016 # Only 8 characters of $username appear in some output.
1017 if test `echo $username |wc -c` -gt 8; then
1018   username8=`echo $username |sed 's/^\(........\).*/\1/'`
1019 else
1020   username8=$username
1021 fi
1022
1023 # Rarely, we need to match any username, not just the name of the user
1024 # running this test.  This variable usually shouldn't be used.  $username
1025 # contains the name of the user actually running this test.
1026 #
1027 # I believe this only ever actually gets compared to usernames created by this
1028 # test.  It used to be compared to the username of the user running this test,
1029 # but this hasn't been true for a long time.  Regardless, I tried to get the
1030 # allowed character set right, based on a list in a private email from Mark
1031 # Baushke, basically the allowed names from Linux systems (plus `.', which is
1032 # only allowed on Gentoo Linux as of 2005-09-13).
1033 anyusername="[_a-zA-Z0-9][-_.$a-zA-Z0-9]*"
1034
1035 # now make sure that tr works on NULs
1036 tr_tooltest1 ()
1037 {
1038 tr=$1
1039 if $EXPR `echo "123" | $tr '2' '\0'` : "123" >/dev/null 2>&1; then
1040   echo 'Warning: you are using a version of tr which does not correctly'
1041   echo 'handle NUL bytes.  Some tests may spuriously pass or fail.'
1042   echo 'You may wish to make sure GNU tr is in your path.'
1043   return 77
1044 fi
1045 # good, it works
1046 return 0
1047 }
1048
1049 TR=`find_tool ${TR}:gtr version_test tr_tooltest1`
1050 echo "Using TR=$TR" >>$LOGFILE
1051
1052 # MacOS X (10.2.8) has a /bin/ls that does not work correctly in that
1053 # it will return true even if the wildcard argument does not match any
1054 # files.
1055 ls_tooltest ()
1056 {
1057 ls=$1
1058 # Force cleanup
1059 if test -d $TESTDIR/ls-test; then
1060     chmod -R a+wx $TESTDIR/ls-test
1061     rm -rf $TESTDIR/ls-test
1062 fi
1063 if $ls $TESTDIR/ls-test >/dev/null 2>&1; then
1064   echo "Notice: \`$ls' is defective."
1065   echo 'This is a version of ls which does not correctly'
1066   echo 'return false for files that do not exist. Some tests may'
1067   echo 'spuriously pass or fail.'
1068   echo 'You may wish to put a an ls from GNU coreutils into your path.'
1069   return 77
1070 else
1071   return 0
1072 fi
1073 }
1074 LS=`find_tool ls:gls version_test ls_tooltest`
1075 echo "Using LS=$LS" >>$LOGFILE
1076
1077 # Awk testing
1078
1079 awk_tooltest1 ()
1080 {
1081 awk=$1
1082 $awk 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
1083 if $EXPR "`cat abc`" : \
1084 'one
1085 two
1086 three
1087 four
1088 five
1089 six'; then
1090   rm abc
1091   return 0
1092 else
1093   rm abc
1094   echo "Notice: awk BEGIN clause or printf is not be working properly."
1095   return 1
1096 fi
1097 }
1098
1099 # Format item %c check
1100 awk_tooltest2 ()
1101 {
1102 awk=$1
1103 $awk 'BEGIN { printf "%c%c%c", 2, 3, 4 }' </dev/null \
1104   | ${TR} '\002\003\004' '123' >abc
1105 if $EXPR "`cat abc`" : "123" ; then
1106   : good, found it
1107 else
1108   echo "Notice: awk format %c string may not be working properly."
1109   rm abc
1110   return 77
1111 fi
1112 rm abc
1113 return 0
1114 }
1115
1116 AWK=`find_tool gawk:nawk:awk version_test awk_tooltest1 awk_tooltest2`
1117 echo "Using AWK=$AWK" >>$LOGFILE
1118
1119
1120 ###
1121 ### Functions used by tests.
1122 ###
1123
1124 # Execute a command on the repository, syncing when done if necessary.
1125 #
1126 # Syntax is as `eval'.
1127 modify_repo ()
1128 {
1129     eval "$*"
1130     if $proxy; then
1131         # And now resync the secondary.
1132         $TESTDIR/sync-secondary "repo modification" modify_repo ALL "$@"
1133     fi
1134 }
1135
1136 # Restore changes to CVSROOT admin files.
1137 restore_adm ()
1138 {
1139     modify_repo rm -rf $CVSROOT_DIRNAME/CVSROOT
1140     modify_repo cp -Rp $TESTDIR/CVSROOT.save $CVSROOT_DIRNAME/CVSROOT
1141 }
1142
1143 # Test that $RSYNC supports the options we need or try to find a
1144 # replacement. If $RSYNC works or we replace it, and return 0.
1145 # Otherwise, set $skipreason and return 77.
1146 require_rsync ()
1147 {
1148   rsyncworks=false
1149   # rsync is NOT a GNU tool, so do NOT use find_tool for name munging.
1150   for rsync in ${RSYNC} `Which -a rsync`;
1151   do
1152
1153     if is_bad_tool `Which $rsync` ; then continue ; fi
1154     # Make some data to test rsync on.
1155     mkdir $TESTDIR/rsync-test
1156     mkdir $TESTDIR/rsync-test/Attic && touch $TESTDIR/rsync-test/Attic/6
1157     mkdir $TESTDIR/rsync-test/otherdir && touch $TESTDIR/rsync-test/otherdir/7
1158     for file in 1 2 3 4 5; do
1159       touch $TESTDIR/rsync-test/$file
1160     done
1161   
1162     if test -f "$rsync" && test -r "$rsync" \
1163       && $rsync -rglop --delete $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy \
1164               >/dev/null 2>&1 \
1165       && $rsync -rglop --delete --include Attic --exclude '*/' \
1166               $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy2 \
1167               >/dev/null 2>&1 \
1168       && test -f $TESTDIR/rsync-test/5 \
1169       && mv $TESTDIR/rsync-test/5 $TESTDIR/rsync-test/Attic/5 \
1170       && test -f $TESTDIR/rsync-test-copy/Attic/6 \
1171       && $rsync -rglop --delete $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy \
1172               >/dev/null 2>&1 \
1173       && $rsync -rglop --delete --include Attic --exclude '*/' \
1174               $TESTDIR/rsync-test/ $TESTDIR/rsync-test-copy2 \
1175               >/dev/null 2>&1 \
1176       && test ! -f $TESTDIR/rsync-test-copy/5 \
1177       && test ! -f $TESTDIR/rsync-test-copy2/5 \
1178       && test -f $TESTDIR/rsync-test-copy2/Attic/5 \
1179       && test ! -f $TESTDIR/rsync-test-copy2/otherdir/7
1180     then
1181       # good, it works
1182       rsyncworks=:
1183       RSYNC=$rsync
1184     else
1185       # Only use Which because of ${RSYNC} in the for loop.
1186       set_bad_tool `Which $rsync`
1187     fi
1188   
1189     rm -rf $TESTDIR/rsync-test $TESTDIR/rsync-test-copy \
1190        $TESTDIR/rsync-test-copy2
1191
1192     if $rsyncworks; then
1193       return 0
1194     else
1195       (echo $rsync failed to work properly;\
1196        echo "$rsync --version"; $rsync --version) >>$LOGFILE 2>&1
1197     fi
1198   done
1199
1200   unset RSYNC
1201   skipreason="unusable or no rsync found"
1202   return 77
1203 }
1204
1205 # Test that $1 works as a remote shell.  If so, set $host, $CVS_RSH, &
1206 # $save_CVS_RSH to match and return 0.  Otherwise, set $skipreason and return
1207 # 77.
1208 require_rsh ()
1209 {
1210   if test x"$DISABLE_ANY_RSH" = x"1"; then
1211     skipreason="administratively prohibited"
1212     return 77
1213   fi
1214
1215   host=${remotehost-"`hostname`"}
1216   result=`$1 $host 'echo test'`
1217   rc=$?
1218   if test $? != 0 || test "x$result" != "xtest"; then
1219     skipreason="\`$1 $host' failed rc=$rc result=$result"
1220     return 77
1221   fi
1222
1223   save_CVS_RSH=$CVS_RSH
1224   CVS_RSH=$1; export CVS_RSH
1225   return 0
1226 }
1227
1228 # Find a usable SSH.  When a usable ssh is found, set $host, $CVS_RSH, and
1229 # $save_CVS_RSH and return 0.  Otherwise, set $skipreason and return 77.
1230 require_ssh ()
1231 {
1232   case "$CVS_RSH" in
1233     *ssh*|*putty*)
1234       tryssh=`Which $CVS_RSH`
1235       if [ ! -n "$tryssh" ]; then
1236         skipreason="Unable to find CVS_RSH=$CVS_RSH executable"
1237         return 77
1238       elif [ ! -x "$tryssh" ]; then
1239         skipreason="Unable to execute $tryssh program"
1240         return 77
1241       fi
1242       ;;
1243     *)
1244       # Look in the user's PATH for "ssh"
1245       tryssh=`Which ssh`
1246       if test ! -r "$tryssh"; then
1247         skipreason="Unable to find ssh program"
1248         return 77
1249       fi
1250       ;;
1251   esac
1252
1253   require_rsh "$tryssh"
1254   return $?
1255 }
1256
1257 pass ()
1258 {
1259   echo "PASS: $1" >>${LOGFILE}
1260   passed=`expr $passed + 1`
1261 }
1262
1263 # Like skip(), but don't fail when $skipfail is set.
1264 skip_always ()
1265 {
1266   echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
1267   skipped=`expr $skipped + 1`
1268 }
1269
1270 skip ()
1271 {
1272   if $skipfail; then
1273     # exits
1274     fail "$1${2+ ($2)}"
1275   fi
1276
1277   skip_always ${1+"$@"}
1278 }
1279
1280 # Convenience function for skipping tests run only in remote mode.
1281 remoteonly ()
1282 {
1283   skip_always $1 "only tested in remote mode"
1284 }
1285
1286 # Convenience function for skipping tests not run in proxy mode.
1287 notproxy ()
1288 {
1289   skip_always $1 "not tested in proxy mode"
1290 }
1291
1292 # Convenience function for skipping tests not run in proxy mode.
1293 notnoredirect ()
1294 {
1295   skip_always $1 "not tested in proxy-noredirect mode"
1296 }
1297
1298 warn ()
1299 {
1300   if $skipfail; then
1301     fail "$1${2+ ($2)}"
1302   else
1303     echo "WARNING: $1${2+ ($2)}" >>$LOGFILE
1304   fi
1305   warnings=`expr $warnings + 1`
1306 }
1307
1308 fail ()
1309 {
1310   echo "FAIL: $1" | tee -a ${LOGFILE}
1311   echo "*** Please see the \`TESTS' and \`check.log' files for more information." >&2
1312   # This way the tester can go and see what remnants were left
1313   exit 1
1314 }
1315
1316 verify_tmp_empty ()
1317 {
1318   # Test our temp directory for cvs-serv* directories and cvsXXXXXX temp
1319   # files.  We would like to not leave any behind.
1320   if $remote && $LS $TMPDIR/cvs-serv* >/dev/null 2>&1; then
1321     # A true value means ls found files/directories with these names.
1322     # Give the server some time to finish, then retry.
1323     sleep 2
1324     if $LS $TMPDIR/cvs-serv* >/dev/null 2>&1; then
1325       warn "$1" "Found cvs-serv* directories in $TMPDIR."
1326       # The above will exit if $skipfail
1327       rm -rf $TMPDIR/cvs-serv*
1328     fi
1329   fi
1330   if $LS $TMPDIR/cvs?????? >/dev/null 2>&1; then
1331     # A true value means ls found files/directories with these names.
1332     warn "$1" "Found cvsXXXXXX temp files in $TMPDIR."
1333     # The above will exit if $skipfail
1334     rm -f ls $TMPDIR/cvs??????
1335   fi
1336 }
1337
1338 # See dotest and dotest_fail for explanation (this is the parts
1339 # of the implementation common to the two).
1340 dotest_internal ()
1341 {
1342   if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$3${ENDANCHOR}" >/dev/null; then
1343     # Why, I hear you ask, do we write this to the logfile
1344     # even when the test passes?  The reason is that the test
1345     # may give us the regexp which we were supposed to match,
1346     # but sometimes it may be useful to look at the exact
1347     # text which was output.  For example, suppose one wants
1348     # to grep for a particular warning, and make _sure_ that
1349     # CVS never hits it (even in cases where the tests might
1350     # match it with .*).  Or suppose one wants to see the exact
1351     # date format output in a certain case (where the test will
1352     # surely use a somewhat non-specific pattern).
1353     cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1354     pass "$1"
1355     verify_tmp_empty "$1"
1356   # expr can't distinguish between "zero characters matched" and "no match",
1357   # so special-case it.
1358   elif test -z "$3" && test ! -s ${TESTDIR}/dotest.tmp; then
1359     pass "$1"
1360     verify_tmp_empty "$1"
1361   elif test x"$4" != x; then
1362     if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$4${ENDANCHOR}" >/dev/null; then
1363       cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1364       pass "$1"
1365       verify_tmp_empty "$1"
1366     else
1367       echo "** expected: " >>${LOGFILE}
1368       echo "$3" >>${LOGFILE}
1369       echo "$3" > ${TESTDIR}/dotest.ex1
1370       echo "** or: " >>${LOGFILE}
1371       echo "$4" >>${LOGFILE}
1372       echo "$4" > ${TESTDIR}/dotest.ex2
1373       echo "** got: " >>${LOGFILE}
1374       cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1375       fail "$1"
1376     fi
1377   else
1378     echo "** expected: " >>${LOGFILE}
1379     echo "$3" >>${LOGFILE}
1380     echo "$3" > ${TESTDIR}/dotest.exp
1381     echo "** got: " >>${LOGFILE}
1382     cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1383     fail "$1"
1384   fi
1385 }
1386
1387 dotest_all_in_one ()
1388 {
1389   if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : \
1390          "`cat ${TESTDIR}/dotest.exp`" >/dev/null; then
1391     return 0
1392   fi
1393   return 1
1394 }
1395
1396 # WARNING: this won't work with REs that match newlines....
1397 #
1398 dotest_line_by_line ()
1399 {
1400   line=1
1401   while [ $line -le `wc -l <${TESTDIR}/dotest.tmp` ] ; do
1402     if $EXPR "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" : \
1403        "`sed -n ${line}p ${TESTDIR}/dotest.exp`" >/dev/null; then
1404       :
1405     elif test -z "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" &&
1406        test -z "`sed -n ${line}p ${TESTDIR}/dotest.exp`"; then
1407       :
1408     else
1409       echo "Line $line:" >> ${LOGFILE}
1410       echo "**** expected: " >>${LOGFILE}
1411       sed -n ${line}p ${TESTDIR}/dotest.exp >>${LOGFILE}
1412       echo "**** got: " >>${LOGFILE}
1413       sed -n ${line}p ${TESTDIR}/dotest.tmp >>${LOGFILE}
1414       unset line
1415       return 1
1416     fi
1417     line=`expr $line + 1`
1418   done
1419   unset line
1420   return 0
1421 }
1422
1423 # If you are having trouble telling which line of a multi-line
1424 # expression is not being matched, replace calls to dotest_internal()
1425 # with calls to this function:
1426 #
1427 dotest_internal_debug ()
1428 {
1429   if test -z "$3"; then
1430     if test -s ${TESTDIR}/dotest.tmp; then
1431       echo "** expected: " >>${LOGFILE}
1432       echo "$3" >>${LOGFILE}
1433       echo "$3" > ${TESTDIR}/dotest.exp
1434       rm -f ${TESTDIR}/dotest.ex2
1435       echo "** got: " >>${LOGFILE}
1436       cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1437       fail "$1"
1438     else
1439       pass "$1"
1440       verify_tmp_empty "$1"
1441     fi
1442   else
1443     echo "$3" > ${TESTDIR}/dotest.exp
1444     if dotest_line_by_line "$1" "$2"; then
1445       pass "$1"
1446       verify_tmp_empty "$1"
1447     else
1448       if test x"$4" != x; then
1449         mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex1
1450         echo "$4" > ${TESTDIR}/dotest.exp
1451         if dotest_line_by_line "$1" "$2"; then
1452           pass "$1"
1453           verify_tmp_empty "$1"
1454         else
1455           mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex2
1456           echo "** expected: " >>${LOGFILE}
1457           echo "$3" >>${LOGFILE}
1458           echo "** or: " >>${LOGFILE}
1459           echo "$4" >>${LOGFILE}
1460           echo "** got: " >>${LOGFILE}
1461           cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1462           fail "$1"
1463         fi
1464       else
1465         echo "** expected: " >>${LOGFILE}
1466         echo "$3" >>${LOGFILE}
1467         echo "** got: " >>${LOGFILE}
1468         cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
1469         fail "$1"
1470       fi
1471     fi
1472   fi
1473 }
1474
1475 # This function allows the test output to be filtered before being verified.
1476 # The dotest_* functions all call this function, which runs the command
1477 # in the env var $TEST_FILTER on its argument if $TEST_FILTER is set.  If
1478 # $TEST_FILTER is not set, this function does nothing.
1479 #
1480 # I found this primarily useful when running the test suite on a CVS
1481 # executable linked with memory and function profilers which can generate
1482 # spurious output.
1483 run_filter ()
1484 {
1485   if test -n "$TEST_FILTER"; then
1486     # Make sure there is an EOL
1487     echo >>$1
1488     sed '${/^$/d}' <$1 >$1.filter1
1489     # Run the filter
1490     eval "$TEST_FILTER" <$1.filter1 >$1.filter2
1491     diff -u $1 $1.filter2 \
1492             >$1.diff
1493     mv $1.filter2 $1
1494     rm $1.filter1
1495   fi
1496 }
1497
1498 # Usage:
1499 #  dotest TESTNAME COMMAND OUTPUT [OUTPUT2]
1500 # TESTNAME is the name used in the log to identify the test.
1501 # COMMAND is the command to run; for the test to pass, it exits with
1502 # exitstatus zero.
1503 # OUTPUT is a regexp which is compared against the output (stdout and
1504 # stderr combined) from the test.  It is anchored to the start and end
1505 # of the output, so should start or end with ".*" if that is what is desired.
1506 # Trailing newlines are stripped from the command's actual output before
1507 # matching against OUTPUT.
1508 # If OUTPUT2 is specified and the output matches it, then it is also
1509 # a pass (partial workaround for the fact that some versions of expr
1510 # lack \|).
1511 dotest ()
1512 {
1513   #echo dotest >$TESTDIR/_dotest.fun
1514   #pwd >$TESTDIR/_dotest.cwd
1515   #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
1516   rm -f $TESTDIR/dotest.ex? 2>&1
1517   eval "$2" >$TESTDIR/dotest.tmp 2>&1
1518   status=$?
1519   run_filter $TESTDIR/dotest.tmp
1520   if test "$status" != 0; then
1521     cat $TESTDIR/dotest.tmp >>$LOGFILE
1522     echo "exit status was $status" >>${LOGFILE}
1523     fail "$1"
1524   fi
1525   dotest_internal "$@"
1526 }
1527
1528 # Like dotest except only 2 args and result must exactly match stdin
1529 dotest_lit ()
1530 {
1531   #echo dotest_lit >$TESTDIR/_dotest.fun
1532   #pwd >$TESTDIR/_dotest.cwd
1533   #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
1534   rm -f $TESTDIR/dotest.ex? 2>&1
1535   eval "$2" >$TESTDIR/dotest.tmp 2>&1
1536   status=$?
1537   run_filter $TESTDIR/dotest.tmp
1538   if test "$status" != 0; then
1539     cat $TESTDIR/dotest.tmp >>$LOGFILE
1540     echo "exit status was $status" >>$LOGFILE
1541     fail "$1"
1542   fi
1543   cat >$TESTDIR/dotest.exp
1544   if cmp $TESTDIR/dotest.exp $TESTDIR/dotest.tmp >/dev/null 2>&1; then
1545     pass "$1"
1546     verify_tmp_empty "$1"
1547   else
1548     echo "** expected: " >>$LOGFILE
1549     cat $TESTDIR/dotest.exp >>$LOGFILE
1550     echo "** got: " >>$LOGFILE
1551     cat $TESTDIR/dotest.tmp >>$LOGFILE
1552     fail "$1"
1553   fi
1554 }
1555
1556 # Like dotest except exitstatus should be nonzero.
1557 dotest_fail ()
1558 {
1559   #echo dotest_fail >$TESTDIR/_dotest.fun
1560   #pwd >$TESTDIR/_dotest.cwd
1561   #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
1562   rm -f $TESTDIR/dotest.ex? 2>&1
1563   eval "$2" >$TESTDIR/dotest.tmp 2>&1
1564   status=$?
1565   run_filter $TESTDIR/dotest.tmp
1566   if test "$status" = 0; then
1567     cat $TESTDIR/dotest.tmp >>$LOGFILE
1568     echo "exit status was $status" >>$LOGFILE
1569     fail "$1"
1570   fi
1571   dotest_internal "$@"
1572 }
1573
1574 # Like dotest except output is sorted.
1575 dotest_sort ()
1576 {
1577   #echo dotest_sort >$TESTDIR/_dotest.fun
1578   #pwd >$TESTDIR/_dotest.cwd
1579   #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
1580   rm -f $TESTDIR/dotest.ex? 2>&1
1581   eval "$2" >$TESTDIR/dotest.tmp1 2>&1
1582   status=$?
1583   run_filter $TESTDIR/dotest.tmp1
1584   if test "$status" != 0; then
1585     cat $TESTDIR/dotest.tmp1 >>$LOGFILE
1586     echo "exit status was $status" >>$LOGFILE
1587     fail "$1"
1588   fi
1589   $TR ' ' ' ' < $TESTDIR/dotest.tmp1 | sort > $TESTDIR/dotest.tmp
1590   dotest_internal "$@"
1591 }
1592
1593 # Like dotest_fail except output is sorted.
1594 dotest_fail_sort ()
1595 {
1596   #echo dotest_fail_sort >$TESTDIR/_dotest.fun
1597   #pwd >$TESTDIR/_dotest.cwd
1598   #printf '%s\n' "$2" >$TESTDIR/_dotest.cmd
1599   rm -f $TESTDIR/dotest.ex? 2>&1
1600   eval "$2" >$TESTDIR/dotest.tmp1 2>&1
1601   status=$?
1602   run_filter $TESTDIR/dotest.tmp1
1603   if test "$status" = 0; then
1604     cat $TESTDIR/dotest.tmp1 >>$LOGFILE
1605     echo "exit status was $status" >>$LOGFILE
1606     fail "$1"
1607   fi
1608   $TR ' ' ' ' < $TESTDIR/dotest.tmp1 | sort > $TESTDIR/dotest.tmp
1609   dotest_internal "$@"
1610 }
1611
1612 # A function for fetching the timestamp of a revison of a file
1613 getrlogdate () {
1614     ${testcvs} -n rlog -N ${1+"$@"} |
1615     while read token value; do
1616         case "$token" in
1617         date:)
1618             echo $value | sed "s,;.*,,"
1619             break;
1620             ;;
1621         esac
1622     done
1623 }
1624
1625 # Avoid picking up any stray .cvsrc, etc., from the user running the tests
1626 mkdir home
1627 HOME=$TESTDIR/home; export HOME
1628
1629 # Make sure this variable is not defined to anything that would
1630 # change the format of rcs dates.  Otherwise people using e.g.,
1631 # RCSINIT=-zLT get lots of spurious failures.
1632 RCSINIT=; export RCSINIT
1633
1634 # Remaining arguments are the names of tests to run.
1635 #
1636 # The testsuite is broken up into (hopefully manageably-sized)
1637 # independently runnable tests, so that one can quickly get a result
1638 # from a cvs or testsuite change, and to facilitate understanding the
1639 # tests.
1640
1641 if test x"$*" = x; then
1642         # Basic/miscellaneous functionality
1643         tests="version basica basicb basicc basic1 deep basic2 ls"
1644         tests="$tests parseroot parseroot2 parseroot3 files spacefiles"
1645         tests="${tests} commit-readonly commit-add-missing"
1646         tests="${tests} status"
1647         tests="${tests} suck"
1648         # Branching, tagging, removing, adding, multiple directories
1649         tests="${tests} rdiff rdiff-short"
1650         tests="${tests} rdiff2 diff diffnl death death2"
1651         tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
1652         tests="${tests} dirs dirs2 branches branches2 branches3"
1653         tests="${tests} branches4 tagc tagf tag-space"
1654         tests="${tests} rcslib multibranch import importb importc importX"
1655         tests="$tests importX2 import-CVS import-quirks"
1656         tests="${tests} update-p import-after-initial branch-after-import"
1657         tests="${tests} join join2 join3 join4 join5 join6 join7"
1658         tests="${tests} join-readonly-conflict join-admin join-admin-2"
1659         tests="${tests} join-rm"
1660         tests="${tests} new newb conflicts conflicts2 conflicts3"
1661         tests="${tests} clean"
1662         tests="${tests} keywordexpand"
1663         # Checking out various places (modules, checkout -d, &c)
1664         tests="${tests} modules modules2 modules3 modules4 modules5 modules6"
1665         tests="${tests} modules7 mkmodules co-d"
1666         tests="${tests} cvsadm emptydir abspath abspath2 toplevel toplevel2"
1667         tests="${tests} rstar-toplevel trailingslashes checkout_repository"
1668         # Log messages, error messages.
1669         tests="${tests} mflag editor env errmsg1 errmsg2 adderrmsg opterrmsg"
1670         tests="${tests} errmsg3"
1671         tests="${tests} close-stdout"
1672         tests="$tests debug-log-nonfatal"
1673         # Watches, binary files, history browsing, &c.
1674         tests="${tests} devcom devcom2 devcom3 watch4 watch5 watch6-0 watch6"
1675         tests="${tests} edit-check"
1676         tests="${tests} unedit-without-baserev"
1677         tests="${tests} ignore ignore-on-branch binfiles binfiles2 binfiles3"
1678         tests="${tests} mcopy binwrap binwrap2"
1679         tests="${tests} binwrap3 mwrap info taginfo posttag"
1680         tests="$tests config config2 config3 config4"
1681         tests="${tests} serverpatch log log2 logopt ann ann-id"
1682         # Repository Storage (RCS file format, CVS lock files, creating
1683         # a repository without "cvs init", &c).
1684         tests="${tests} crerepos rcs rcs2 rcs3 rcs4 rcs5"
1685         tests="$tests lockfiles backuprecover"
1686         tests="${tests} sshstdio"
1687         # More history browsing, &c.
1688         tests="${tests} history"
1689         tests="${tests} big modes modes2 modes3 stamps"
1690         # PreservePermissions stuff: permissions, symlinks et al.
1691         # tests="${tests} perms symlinks symlinks2 hardlinks"
1692         # More tag and branch tests, keywords.
1693         tests="${tests} sticky keyword keywordlog keywordname keyword2"
1694         tests="${tests} head tagdate multibranch2 tag8k"
1695         # "cvs admin", reserved checkouts.
1696         tests="${tests} admin reserved"
1697         # Nuts and bolts of diffing/merging (diff library, &c)
1698         tests="${tests} diffmerge1 diffmerge2"
1699         # Release of multiple directories
1700         tests="${tests} release"
1701         tests="${tests} recase"
1702         # Multiple root directories and low-level protocol tests.
1703         tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
1704         tests="${tests} rmroot reposmv pserver server server2 client"
1705         tests="${tests} dottedroot fork commit-d template"
1706         tests="${tests} writeproxy writeproxy-noredirect writeproxy-ssh"
1707         tests="${tests} writeproxy-ssh-noredirect"
1708 else
1709         tests="$*"
1710 fi
1711
1712 # Now check the -f argument for validity.
1713 if test -n "$fromtest"; then
1714         # Don't allow spaces - they are our delimiters in tests
1715         count=0
1716         for sub in $fromtest; do
1717           count=`expr $count + 1`
1718         done
1719         if test $count != 1; then
1720                 echo "No such test \`$fromtest'." >&2
1721                 exit 2
1722         fi
1723         # make sure it is in $tests
1724         case " $tests " in
1725                 *" $fromtest "*)
1726                         ;;
1727                 *)
1728                         echo "No such test \`$fromtest'." >&2
1729                         exit 2
1730                         ;;
1731         esac
1732 fi
1733
1734
1735
1736 # a simple function to compare directory contents
1737 #
1738 # Returns: 0 for same, 1 for different
1739 #
1740 directory_cmp ()
1741 {
1742         OLDPWD=`pwd`
1743         DIR_1=$1
1744         DIR_2=$2
1745
1746         cd $DIR_1
1747         find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d1
1748
1749         # go back where we were to avoid symlink hell...
1750         cd $OLDPWD
1751         cd $DIR_2
1752         find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d2
1753
1754         if diff $TESTDIR/dc$$d1 $TESTDIR/dc$$d2 >/dev/null 2>&1
1755         then
1756                 :
1757         else
1758                 return 1
1759         fi
1760         cd $OLDPWD
1761         while read a
1762         do
1763                 if test -f $DIR_1/"$a" ; then
1764                         cmp -s $DIR_1/"$a" $DIR_2/"$a"
1765                         if test $? -ne 0 ; then
1766                                 return 1
1767                         fi
1768                 fi
1769         done < $TESTDIR/dc$$d1
1770         rm -f $TESTDIR/dc$$*
1771         return 0
1772 }
1773
1774
1775
1776 #
1777 # The following 4 functions are used by the diffmerge1 test case.  They set up,
1778 # respectively, the four versions of the files necessary:
1779 #
1780 #       1.  Ancestor revisions.
1781 #       2.  "Your" changes.
1782 #       3.  "My" changes.
1783 #       4.  Expected merge result.
1784 #
1785
1786 # Create ancestor revisions for diffmerge1
1787 diffmerge_create_older_files() {
1788           # This test case was supplied by Noah Friedman:
1789           cat >testcase01 <<EOF
1790 // Button.java
1791
1792 package random.application;
1793
1794 import random.util.*;
1795
1796 public class Button
1797 {
1798   /* Instantiates a Button with origin (0, 0) and zero width and height.
1799    * You must call an initializer method to properly initialize the Button.
1800    */
1801   public Button ()
1802   {
1803     super ();
1804
1805     _titleColor = Color.black;
1806     _disabledTitleColor = Color.gray;
1807     _titleFont = Font.defaultFont ();
1808   }
1809
1810   /* Convenience constructor for instantiating a Button with
1811    * bounds x, y, width, and height.  Equivalent to
1812    *     foo = new Button ();
1813    *     foo.init (x, y, width, height);
1814    */
1815   public Button (int x, int y, int width, int height)
1816   {
1817     this ();
1818     init (x, y, width, height);
1819   }
1820 }
1821 EOF
1822
1823           # This test case was supplied by Jacob Burckhardt:
1824           cat >testcase02 <<EOF
1825 a
1826 a
1827 a
1828 a
1829 a
1830 EOF
1831
1832           # This test case was supplied by Karl Tomlinson who also wrote the
1833           # patch which lets CVS correctly handle this and several other cases:
1834           cat >testcase03 <<EOF
1835 x
1836 s
1837 a
1838 b
1839 s
1840 y
1841 EOF
1842
1843           # This test case was supplied by Karl Tomlinson:
1844           cat >testcase04 <<EOF
1845 s
1846 x
1847 m
1848 m
1849 x
1850 s
1851 v
1852 s
1853 x
1854 m
1855 m
1856 x
1857 s
1858 EOF
1859
1860           # This test case was supplied by Karl Tomlinson:
1861           cat >testcase05 <<EOF
1862 s
1863 x
1864 m
1865 m
1866 x
1867 x
1868 x
1869 x
1870 x
1871 x
1872 x
1873 x
1874 x
1875 x
1876 s
1877 s
1878 s
1879 s
1880 s
1881 s
1882 s
1883 s
1884 s
1885 s
1886 v
1887 EOF
1888
1889           # This test case was supplied by Jacob Burckhardt:
1890           cat >testcase06 <<EOF
1891 g
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903 i
1904 EOF
1905
1906           # This test is supposed to verify that the horizon lines are the same
1907           # for both 2-way diffs, but unfortunately, it does not fail with the
1908           # old version of cvs.  However, Karl Tomlinson still thought it would
1909           # be good to test it anyway:
1910           cat >testcase07 <<EOF
1911 h
1912 f
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 g
1923 r
1924
1925
1926
1927 i
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938 i
1939 EOF
1940
1941           # This test case was supplied by Jacob Burckhardt:
1942           cat >testcase08 <<EOF
1943 Both changes move this line to the end of the file.
1944
1945 no
1946 changes
1947 here
1948
1949 First change will delete this line.
1950
1951 First change will also delete this line.
1952
1953     no
1954     changes
1955     here
1956
1957 Second change will change it here.
1958
1959         no
1960         changes
1961         here
1962 EOF
1963
1964           # This test case was supplied by Jacob Burckhardt.  Note that I do not
1965           # think cvs has ever failed with this case, but I include it anyway,
1966           # since I think it is a hard case.  It is hard because Peter Miller's
1967           # fmerge utility fails on it:
1968           cat >testcase09 <<EOF
1969 m
1970 a
1971 {
1972 }
1973 b
1974 {
1975 }
1976 EOF
1977
1978           # This test case was supplied by Martin Dorey and simplified by Jacob
1979           # Burckhardt:
1980           cat >testcase10 <<EOF
1981
1982     petRpY ( MtatRk );
1983     fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
1984
1985     MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
1986     OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
1987
1988     Bloke_GttpfIRte_MtpeaL ( &acI );
1989 MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
1990 {
1991     fV ( Y < 16 )
1992     {
1993         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
1994                                                       Y * jfle_Uecopd_MfJe_fY_Mectopk,
1995                                 jfle_Uecopd_MfJe_fY_Mectopk,
1996                                 nRVVep ) );
1997     }
1998     elke
1999     {
2000         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2001                                                  ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
2002                                 jfle_Uecopd_MfJe_fY_Mectopk,
2003                                 nRVVep ) );
2004     }
2005
2006 }
2007
2008
2009 /****************************************************************************
2010 *                                                                           *
2011 *   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
2012 *                                                                           *
2013 ****************************************************************************/
2014
2015 MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
2016 {
2017 MTGTXM MtatRk = Zy;
2018
2019     MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
2020
2021     petRpY ( MtatRk );
2022
2023 }
2024     HfkQipfte ( waYdle,                 /*  waYdle                         */
2025                 waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
2026                 (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
2027                 0,                      /*  MRrepVlRoRk KfxoYfkL           */
2028                 beYgtz                  /*  nEtek to Apfte                 */
2029               );
2030
2031     petRpY ( Zy );
2032 }
2033 EOF
2034 }
2035
2036 # Create "your" revisions for diffmerge1
2037 diffmerge_create_your_files() {
2038           # remove the Button() method
2039           cat >testcase01 <<\EOF
2040 // Button.java
2041
2042 package random.application;
2043
2044 import random.util.*;
2045
2046 public class Button
2047 {
2048   /* Instantiates a Button with origin (0, 0) and zero width and height.
2049    * You must call an initializer method to properly initialize the Button.
2050    */
2051   public Button ()
2052   {
2053     super ();
2054
2055     _titleColor = Color.black;
2056     _disabledTitleColor = Color.gray;
2057     _titleFont = Font.defaultFont ();
2058   }
2059 }
2060 EOF
2061
2062           cat >testcase02 <<\EOF
2063 y
2064 a
2065 a
2066 a
2067 a
2068 EOF
2069
2070           cat >testcase03 <<\EOF
2071 x
2072 s
2073 a
2074 b
2075 s
2076 b
2077 s
2078 y
2079 EOF
2080
2081           cat >testcase04 <<\EOF
2082 s
2083 m
2084 s
2085 v
2086 s
2087 m
2088 s
2089 EOF
2090
2091           cat >testcase05 <<\EOF
2092 v
2093 s
2094 m
2095 s
2096 s
2097 s
2098 s
2099 s
2100 s
2101 s
2102 s
2103 s
2104 s
2105 v
2106 EOF
2107
2108           # Test case 6 and test case 7 both use the same input files, but they
2109           # order the input files differently.  In one case, a certain file is
2110           # used as the older file, but in the other test case, that same file
2111           # is used as the file which has changes.  I could have put echo
2112           # commands here, but since the echo lines would be the same as those
2113           # in the previous function, I decided to save space and avoid repeating
2114           # several lines of code.  Instead, I merely swap the files:
2115           mv testcase07 tmp
2116           mv testcase06 testcase07
2117           mv tmp testcase06
2118
2119           # Make the date newer so that cvs thinks that the files are changed:
2120           touch testcase06 testcase07
2121
2122           cat >testcase08 <<\EOF
2123 no
2124 changes
2125 here
2126
2127 First change has now added this in.
2128
2129     no
2130     changes
2131     here
2132
2133 Second change will change it here.
2134
2135         no
2136         changes
2137         here
2138
2139 Both changes move this line to the end of the file.
2140 EOF
2141
2142           cat >testcase09 <<\EOF
2143
2144 m
2145 a
2146 {
2147 }
2148 b
2149 {
2150 }
2151 c
2152 {
2153 }
2154 EOF
2155
2156           cat >testcase10 <<\EOF
2157
2158     fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
2159
2160     petRpY ( MtatRk );
2161     fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
2162
2163     fV ( jfle_Uecopd_KRLIep < 16 )
2164     {
2165         MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
2166     }
2167     elke
2168     {
2169         MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
2170         fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
2171
2172         MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
2173         OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
2174
2175     Bloke_GttpfIRte_MtpeaL ( &acI );
2176 MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
2177 {
2178 MTGTXM MtatRk = Zy;
2179
2180     fV ( Y < 16 )
2181     {
2182         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2183                                                       Y * jfle_Uecopd_MfJe_fY_Mectopk,
2184                                 jfle_Uecopd_MfJe_fY_Mectopk,
2185                                 nRVVep ) );
2186     }
2187     elke
2188     {
2189         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2190                                                  ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
2191                                 jfle_Uecopd_MfJe_fY_Mectopk,
2192                                 nRVVep ) );
2193     }
2194
2195     petRpY ( MtatRk );
2196
2197 }
2198
2199
2200 /****************************************************************************
2201 *                                                                           *
2202 *   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
2203 *                                                                           *
2204 ****************************************************************************/
2205
2206 MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
2207 {
2208 MTGTXM MtatRk = Zy;
2209
2210     MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
2211
2212     petRpY ( MtatRk );
2213
2214 }
2215     HfkQipfte ( waYdle,                 /*  waYdle                         */
2216                 waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
2217                 (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
2218                 0,                      /*  MRrepVlRoRk KfxoYfkL           */
2219                 beYgtz                  /*  nEtek to Apfte                 */
2220               );
2221
2222     petRpY ( Zy );
2223 }
2224
2225 EOF
2226 }
2227
2228 # Create "my" revisions for diffmerge1
2229 diffmerge_create_my_files() {
2230           # My working copy still has the Button() method, but I
2231           # comment out some code at the top of the class.
2232           cat >testcase01 <<\EOF
2233 // Button.java
2234
2235 package random.application;
2236
2237 import random.util.*;
2238
2239 public class Button
2240 {
2241   /* Instantiates a Button with origin (0, 0) and zero width and height.
2242    * You must call an initializer method to properly initialize the Button.
2243    */
2244   public Button ()
2245   {
2246     super ();
2247
2248     // _titleColor = Color.black;
2249     // _disabledTitleColor = Color.gray;
2250     // _titleFont = Font.defaultFont ();
2251   }
2252
2253   /* Convenience constructor for instantiating a Button with
2254    * bounds x, y, width, and height.  Equivalent to
2255    *     foo = new Button ();
2256    *     foo.init (x, y, width, height);
2257    */
2258   public Button (int x, int y, int width, int height)
2259   {
2260     this ();
2261     init (x, y, width, height);
2262   }
2263 }
2264 EOF
2265
2266           cat >testcase02 <<\EOF
2267 a
2268 a
2269 a
2270 a
2271 m
2272 EOF
2273
2274           cat >testcase03 <<\EOF
2275 x
2276 s
2277 c
2278 s
2279 b
2280 s
2281 y
2282 EOF
2283
2284           cat >testcase04 <<\EOF
2285 v
2286 s
2287 x
2288 m
2289 m
2290 x
2291 s
2292 v
2293 s
2294 x
2295 m
2296 m
2297 x
2298 s
2299 v
2300 EOF
2301
2302           # Note that in test case 5, there are no changes in the "mine"
2303           # section, which explains why there is no command here which writes to
2304           # file testcase05.
2305
2306           # no changes for testcase06
2307
2308           # The two branches make the same changes:
2309           cp ../yours/testcase07 .
2310
2311           cat >testcase08 <<\EOF
2312 no
2313 changes
2314 here
2315
2316 First change will delete this line.
2317
2318 First change will also delete this line.
2319
2320     no
2321     changes
2322     here
2323
2324 Second change has now changed it here.
2325
2326         no
2327         changes
2328         here
2329
2330 Both changes move this line to the end of the file.
2331 EOF
2332
2333           cat >testcase09 <<\EOF
2334 m
2335 a
2336 {
2337 }
2338 b
2339 {
2340 }
2341 c
2342 {
2343 }
2344 EOF
2345
2346           cat >testcase10 <<\EOF
2347
2348     petRpY ( MtatRk );
2349     fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
2350
2351     MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
2352     OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
2353
2354     Bloke_GttpfIRte_MtpeaL ( &acI );
2355 MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
2356 {
2357     fV ( Y < 16 )
2358     {
2359         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2360                                                       Y * jfle_Uecopd_MfJe_fY_Mectopk,
2361                                 jfle_Uecopd_MfJe_fY_Mectopk,
2362                                 nRVVep ) );
2363     }
2364     elke
2365     {
2366         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2367                                                  ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
2368                                 jfle_Uecopd_MfJe_fY_Mectopk,
2369                                 nRVVep ) );
2370     }
2371
2372 }
2373
2374
2375 /****************************************************************************
2376 *                                                                           *
2377 *   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
2378 *                                                                           *
2379 ****************************************************************************/
2380
2381 MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
2382 {
2383 MTGTXM MtatRk = Zy;
2384
2385     MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
2386
2387     petRpY ( MtatRk );
2388
2389 }
2390     HfkQipfte ( waYdle,                 /*  waYdle                         */
2391                 waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
2392                 (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
2393                 beYgtz                  /*  nEtek to Apfte                 */
2394               );
2395
2396     petRpY ( Zy );
2397 }
2398
2399 EOF
2400 }
2401
2402 # Create expected results of merge for diffmerge1
2403 diffmerge_create_expected_files() {
2404           cat >testcase01 <<\EOF
2405 // Button.java
2406
2407 package random.application;
2408
2409 import random.util.*;
2410
2411 public class Button
2412 {
2413   /* Instantiates a Button with origin (0, 0) and zero width and height.
2414    * You must call an initializer method to properly initialize the Button.
2415    */
2416   public Button ()
2417   {
2418     super ();
2419
2420     // _titleColor = Color.black;
2421     // _disabledTitleColor = Color.gray;
2422     // _titleFont = Font.defaultFont ();
2423   }
2424 }
2425 EOF
2426
2427           cat >testcase02 <<\EOF
2428 y
2429 a
2430 a
2431 a
2432 m
2433 EOF
2434
2435           cat >testcase03 <<\EOF
2436 x
2437 s
2438 c
2439 s
2440 b
2441 s
2442 b
2443 s
2444 y
2445 EOF
2446
2447           cat >testcase04 <<\EOF
2448 v
2449 s
2450 m
2451 s
2452 v
2453 s
2454 m
2455 s
2456 v
2457 EOF
2458
2459           # Since there are no changes in the "mine" section, just take exactly
2460           # the version in the "yours" section:
2461           cp ../yours/testcase05 .
2462
2463           cp ../yours/testcase06 .
2464
2465           # Since the two branches make the same changes, the result should be
2466           # the same as both branches.  Here, I happen to pick yours to copy from,
2467           # but I could have also picked mine, since the source of the copy is
2468           # the same in either case.  However, the mine has already been
2469           # altered by the update command, so don't use it.  Instead, use the
2470           # yours section which has not had an update on it and so is unchanged:
2471           cp ../yours/testcase07 .
2472
2473           cat >testcase08 <<\EOF
2474 no
2475 changes
2476 here
2477
2478 First change has now added this in.
2479
2480     no
2481     changes
2482     here
2483
2484 Second change has now changed it here.
2485
2486         no
2487         changes
2488         here
2489
2490 Both changes move this line to the end of the file.
2491 EOF
2492
2493           cat >testcase09 <<\EOF
2494
2495 m
2496 a
2497 {
2498 }
2499 b
2500 {
2501 }
2502 c
2503 {
2504 }
2505 EOF
2506
2507           cat >testcase10 <<\EOF
2508
2509     fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
2510
2511     petRpY ( MtatRk );
2512     fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
2513
2514     fV ( jfle_Uecopd_KRLIep < 16 )
2515     {
2516         MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
2517     }
2518     elke
2519     {
2520         MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
2521         fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
2522
2523         MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
2524         OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
2525
2526     Bloke_GttpfIRte_MtpeaL ( &acI );
2527 MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
2528 {
2529 MTGTXM MtatRk = Zy;
2530
2531     fV ( Y < 16 )
2532     {
2533         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2534                                                       Y * jfle_Uecopd_MfJe_fY_Mectopk,
2535                                 jfle_Uecopd_MfJe_fY_Mectopk,
2536                                 nRVVep ) );
2537     }
2538     elke
2539     {
2540         petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
2541                                                  ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
2542                                 jfle_Uecopd_MfJe_fY_Mectopk,
2543                                 nRVVep ) );
2544     }
2545
2546     petRpY ( MtatRk );
2547
2548 }
2549
2550
2551 /****************************************************************************
2552 *                                                                           *
2553 *   Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY )                      *
2554 *                                                                           *
2555 ****************************************************************************/
2556
2557 MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
2558 {
2559 MTGTXM MtatRk = Zy;
2560
2561     MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
2562
2563     petRpY ( MtatRk );
2564
2565 }
2566     HfkQipfte ( waYdle,                 /*  waYdle                         */
2567                 waYdleFok,              /*  ZVVket VpoL ktapt oV dfkQ      */
2568                 (coYkt RfYt8*) nRVVep,  /*  nRVVep                         */
2569                 beYgtz                  /*  nEtek to Apfte                 */
2570               );
2571
2572     petRpY ( Zy );
2573 }
2574
2575 EOF
2576 }
2577
2578
2579
2580 # Echo a new CVSROOT based on $1, $remote, and $remotehost
2581 newroot() {
2582   if $remote; then
2583     if test -n "$remotehost"; then
2584       echo :ext$rootoptions:$remotehost$1
2585     else
2586       echo :fork$rootoptions:$1
2587     fi
2588   else
2589     echo $1
2590   fi
2591 }
2592
2593
2594
2595 # Set up CVSROOT (the crerepos tests will test operating without CVSROOT set).
2596 #
2597 # Currently we test :fork: and :ext: (see crerepos test).  There is a
2598 # known difference between the two in modes-15 (see comments there).
2599 #
2600 # :ext: can be tested against a remote machine if:
2601 #
2602 #    1. $remotehost is set using the `-h' option to this script.
2603 #    2. ${CVS_RSH=rsh} $remotehost works.
2604 #    3. The path to $TESTDIR is the same on both machines (symlinks are okay)
2605 #    4. The path to $testcvs is the same on both machines (symlinks are okay)
2606 #       or $CVS_SERVER is overridden in this script's environment to point to
2607 #       a working CVS exectuable on the remote machine.
2608 #
2609 # Testing :pserver: would be hard (inetd issues).  (How about using tcpserver
2610 # and some high port number?  DRP)
2611
2612 if $linkroot; then
2613     mkdir ${TESTDIR}/realcvsroot
2614     ln -s realcvsroot ${TESTDIR}/cvsroot
2615 fi
2616 CVSROOT_DIRNAME=${TESTDIR}/cvsroot
2617 CVSROOT=`newroot $CVSROOT_DIRNAME`; export CVSROOT
2618
2619
2620
2621 ###
2622 ### Initialize the repository
2623 ###
2624 dotest init-1 "$testcvs init"
2625
2626 # We might need to allow "cvs admin" access.
2627 mkdir wnt
2628 cd wnt
2629 dotest init-1a "$testcvs -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
2630 cd CVSROOT
2631 sed -e's/^#UserAdminOptions=/UserAdminOptions=/' <config >tmpconfig
2632 mv tmpconfig config
2633 dotest init-1b "$testcvs -q ci -m allow-cvs-admin" "" \
2634 ".*/CVSROOT/config,v  <--  config
2635 new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
2636 $SPROG commit: Rebuilding administrative file database"
2637 cd ../..
2638 rm -r wnt
2639
2640 # Now hide the primary root behind a secondary if requested.
2641 if $proxy; then
2642     # Save the primary root.
2643     PRIMARY_CVSROOT=$CVSROOT
2644     PRIMARY_CVSROOT_DIRNAME=$CVSROOT_DIRNAME
2645     # Where the secondary root will be
2646     SECONDARY_CVSROOT_DIRNAME=$TESTDIR/secondary_cvsroot
2647     if $noredirect; then
2648         rootoptions=";Redirect=no"
2649         SECONDARY_CVSROOT=`newroot $PRIMARY_CVSROOT_DIRNAME`
2650     else
2651         SECONDARY_CVSROOT=`newroot $SECONDARY_CVSROOT_DIRNAME`
2652     fi
2653     # Now set the global CVSROOT to use the secondary.
2654     CVSROOT=$SECONDARY_CVSROOT; export CVSROOT
2655
2656     require_rsync
2657     if test $? -eq 77; then
2658         echo "Unable to test in proxy mode: $skipreason" >&2
2659         skip all "missing or broken rsync command."
2660         exit 0
2661     fi
2662
2663     if $noredirect; then
2664         # Wrap the CVS server to allow --primary-root to be set by the
2665         # secondary.
2666         cat <<EOF >$TESTDIR/secondary-wrapper
2667 #! $TESTSHELL
2668 CVS_SERVER=$TESTDIR/primary-wrapper
2669 export CVS_SERVER
2670
2671 # No need to check the PID of the last client since we are testing with
2672 # Redirect disabled.
2673 proot_arg="--allow-root=$SECONDARY_CVSROOT_DIRNAME"
2674 exec $CVS_SERVER \$proot_arg "\$@"
2675 EOF
2676         cat <<EOF >$TESTDIR/primary-wrapper
2677 #! $TESTSHELL
2678 if test -n "$CVS_SERVER_LOG"; then
2679   CVS_SERVER_LOG=`dirname "$CVS_SERVER_LOG"`/cvsprimarylog
2680   export CVS_SERVER_LOG
2681 fi
2682 exec $CVS_SERVER "\$@"
2683 EOF
2684
2685         CVS_SERVER_secondary=$TESTDIR/secondary-wrapper
2686         CVS_SERVER=$CVS_SERVER_secondary
2687
2688         chmod a+x $TESTDIR/secondary-wrapper \
2689                   $TESTDIR/primary-wrapper
2690     fi
2691
2692     # Script to sync the secondary root.
2693     cat >$TESTDIR/sync-secondary <<EOF
2694 #! $TESTSHELL
2695 # date >>$TESTDIR/update-log
2696
2697 ps=\$1
2698 cmd=\$2
2699 dir=\$3
2700 shift
2701 shift
2702 shift
2703
2704 # echo "updating from \$ps for command \\\`\$cmd' in dir \\\`\$dir'" \${1+"\$@"} \\
2705 #      >>$TESTDIR/update-log
2706
2707 # If multiple CVS executables could attempt to access the repository, we would
2708 # Need to lock for this sync and sleep
2709 case "\$dir" in
2710   ALL)
2711     # This is a hack to allow a few of the tests to play with the
2712     # UseNewInfoFmtStrings key in CVSROOT/config.  It's inefficient, but there
2713     # aren't many tests than need it and the alternative is an awful lot of
2714     # special casing.
2715     $RSYNC -rglop --delete --exclude '#cvs.*' \\
2716            $PRIMARY_CVSROOT_DIRNAME/ \\
2717            $SECONDARY_CVSROOT_DIRNAME
2718     ;;
2719
2720   *)
2721     # For the majority of the tests we will only sync the directories that
2722     # were written to.
2723     case "\$cmd" in
2724       add|import)
2725         # For \`add', we need a recursive update due to quirks in rsync syntax,
2726         # but it shouldn't affect efficiency since any new dir should be empty.
2727         #
2728         # For \`import', a recursive update is necessary since subdirs may have
2729         # been added underneath the root dir we were passed. 
2730         $RSYNC -rglop \\
2731                $PRIMARY_CVSROOT_DIRNAME/"\$dir" \\
2732                $SECONDARY_CVSROOT_DIRNAME/\`dirname -- "\$dir"\`
2733         ;;
2734
2735       tag)
2736         # \`tag' may have changed CVSROOT/val-tags too.
2737         $RSYNC -glop \\
2738                $PRIMARY_CVSROOT_DIRNAME/CVSROOT/val-tags \\
2739                $SECONDARY_CVSROOT_DIRNAME/CVSROOT
2740         # Otherwise it is identical to other write commands.
2741         $RSYNC -rglop --delete \\
2742                --include Attic --include CVS \
2743                --exclude '#cvs.*' --exclude '*/' \\
2744                $PRIMARY_CVSROOT_DIRNAME/"\$dir"/ \\
2745                $SECONDARY_CVSROOT_DIRNAME/"\$dir"
2746         ;;
2747
2748       *)
2749         # By default, sync just what changed.
2750         $RSYNC -rglop --delete \\
2751                --include Attic --include CVS \
2752                --exclude '#cvs.*' --exclude '*/' \\
2753                $PRIMARY_CVSROOT_DIRNAME/"\$dir"/ \\
2754                $SECONDARY_CVSROOT_DIRNAME/"\$dir"
2755         ;;
2756     esac # \$cmd
2757
2758     # And keep the history file up to date for all commands.
2759     $RSYNC -glop \\
2760            $PRIMARY_CVSROOT_DIRNAME/CVSROOT/history \\
2761            $SECONDARY_CVSROOT_DIRNAME/CVSROOT
2762     ;; # \$dir = *
2763 esac # \$dir
2764
2765 # Avoid timestamp comparison issues with rsync.
2766 sleep 2
2767 EOF
2768     chmod a+x $TESTDIR/sync-secondary
2769
2770     # And now init the secondary.
2771     $TESTDIR/sync-secondary "- no, before - create secondary root" \
2772                             sanity-setup ALL
2773
2774     # Initialize the primary repository
2775     mkdir proxy-init; cd proxy-init
2776     dotest proxy-init-1 "$testcvs -Qd$PRIMARY_CVSROOT co CVSROOT"
2777     cd CVSROOT
2778     cat >>config <<EOF
2779 PrimaryServer=$PRIMARY_CVSROOT
2780 EOF
2781     cat >>loginfo <<EOF
2782 ALL $TESTDIR/sync-secondary loginfo %c %p %{sVv}
2783 EOF
2784     cat >>postadmin <<EOF
2785 ALL $TESTDIR/sync-secondary postadmin %c %p
2786 EOF
2787     cat >>posttag <<EOF
2788 ALL $TESTDIR/sync-secondary posttag %c %p %o %b %t %{sVv}
2789 EOF
2790     cat >>postwatch <<EOF
2791 ALL $TESTDIR/sync-secondary postwatch %c %p
2792 EOF
2793     dotest proxy-init-2 \
2794 "$testcvs -Q ci -mconfigure-writeproxy"
2795
2796     # Save these files for later reference
2797     cp config $TESTDIR/config-clean
2798     cp loginfo $TESTDIR/loginfo-clean
2799     cp postadmin $TESTDIR/postadmin-clean
2800     cp posttag $TESTDIR/posttag-clean
2801     cp postwatch $TESTDIR/postwatch-clean
2802
2803     # done in here
2804     cd ../..
2805     rm -rf proxy-init
2806 else # !$proxy
2807     # Set this even when not testing $proxy to match messages, like $SPROG.
2808     SECONDARY_CVSROOT_DIRNAME=$CVSROOT_DIRNAME
2809 fi # $proxy
2810
2811 # Save a copy of the initial repository so that it may be restored after the
2812 # tests that alter it.
2813 cp -Rp $CVSROOT_DIRNAME/CVSROOT $TESTDIR/CVSROOT.save
2814
2815
2816 ###
2817 ### The tests
2818 ###
2819 dotest init-2 "$testcvs init"
2820
2821 # We might need to allow "cvs admin" access.
2822 mkdir wnt
2823 cd wnt
2824 dotest init-2a "$testcvs -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
2825 cd CVSROOT
2826 sed -e's/^#UserAdminOptions=/UserAdminOptions=/' <config >tmpconfig
2827 mv tmpconfig config
2828 dotest init-2b "$testcvs -q ci -m allow-cvs-admin" "" \
2829 ".*/CVSROOT/config,v  <--  config
2830 new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
2831 $SPROG commit: Rebuilding administrative file database"
2832 cd ../..
2833 rm -r wnt
2834
2835
2836 ###
2837 ### The big loop
2838 ###
2839 for what in $tests; do
2840         if test -n "$fromtest" ; then
2841             if test $fromtest = $what ; then
2842                 unset fromtest
2843             else
2844                 continue
2845             fi
2846         fi
2847         case $what in
2848
2849         version)
2850           # We've had cases where the version command started dumping core,
2851           # so we might as well test it
2852           dotest version-1 "${testcvs} --version" \
2853 '
2854 Concurrent Versions System (CVS) [0-9.]*.*
2855
2856 Copyright (C) [0-9]* Free Software Foundation, Inc.
2857
2858 Portions contributed by Thorsten Glaser for the MirOS Project.
2859 Senior active maintainers include Larry Jones, Derek R. Price,
2860 and Mark D. Baushke.  Please see the AUTHORS and README files from the CVS
2861 distribution kit for a complete list of contributors and copyrights.
2862
2863 CVS may be copied only under the terms of the GNU General Public License,
2864 a copy of which can be found with the CVS distribution kit.
2865
2866 Specify the --help option for further information about CVS'
2867
2868 # Maybe someday...
2869 #         if $proxy; then
2870 #               dotest version-2r "${testcvs} version" \
2871 #'Client: Concurrent Versions System (CVS) [0-9p.]* (client.*)
2872 #Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)
2873 #Secondary Server: Concurrent Versions System (CVS) [0-9p.]* (.*server)'
2874           if $remote; then
2875                 dotest version-2r "${testcvs} version" \
2876 'Client: Concurrent Versions System (CVS) [0-9p.]*\(-Mir[^ ]*\)* (client.*)
2877 Server: Concurrent Versions System (CVS) [0-9p.]*\(-Mir[^ ]*\)* (.*server)'
2878           else
2879                 dotest version-2 "${testcvs} version" \
2880 'Concurrent Versions System (CVS) [0-9.]*.*'
2881           fi
2882           ;;
2883
2884
2885
2886         basica)
2887           # Similar in spirit to some of the basic1, and basic2
2888           # tests, but hopefully a lot faster.  Also tests operating on
2889           # files two directories down *without* operating on the parent dirs.
2890
2891           # Tests basica-0a and basica-0b provide the equivalent of the:
2892           #    mkdir ${CVSROOT_DIRNAME}/first-dir
2893           # used by many of the tests.  It is "more official" in the sense
2894           # that is does everything through CVS; the reason most of the
2895           # tests don't use it is mostly historical.
2896           mkdir 1; cd 1
2897           dotest basica-0a "$testcvs -q co -l ."
2898           mkdir first-dir
2899           dotest basica-0b "$testcvs add first-dir" \
2900 "Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
2901           cd ..
2902           rm -r 1
2903
2904           dotest basica-1 "$testcvs -q co first-dir" ''
2905           cd first-dir
2906
2907           # Test a few operations, to ensure they gracefully do
2908           # nothing in an empty directory.
2909           dotest basica-1a0 "$testcvs -q update"
2910           dotest basica-1a1 "$testcvs -q diff -c"
2911           dotest basica-1a2 "$testcvs -q status"
2912           dotest basica-1a3 "$testcvs -q update ."
2913           dotest basica-1a4 "$testcvs -q update ./"
2914
2915           mkdir sdir
2916           # Remote CVS gives the "cannot open CVS/Entries" error, which is
2917           # clearly a bug, but not a simple one to fix.
2918           dotest basica-1a10 "$testcvs -n add sdir" \
2919 "Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control" \
2920 "$SPROG add: cannot open CVS/Entries for reading: No such file or directory
2921 Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control"
2922           dotest_fail basica-1a11 \
2923             "test -d $CVSROOT_DIRNAME/first-dir/sdir"
2924           dotest basica-2 "$testcvs add sdir" \
2925 "Directory $CVSROOT_DIRNAME/first-dir/sdir put under version control"
2926           cd sdir
2927           mkdir ssdir
2928           dotest basica-3 "$testcvs add ssdir" \
2929 "Directory $CVSROOT_DIRNAME/first-dir/sdir/ssdir put under version control"
2930           cd ssdir
2931           echo ssfile >ssfile
2932
2933           # Trying to commit it without a "cvs add" should be an error.
2934           # The "use `cvs add' to create an entry" message is the one
2935           # that I consider to be more correct, but local cvs prints the
2936           # "nothing known" message and noone has gotten around to fixing it.
2937           dotest_fail basica-notadded "${testcvs} -q ci ssfile" \
2938 "${CPROG} commit: use .${CPROG} add. to create an entry for \`ssfile'
2939 ${CPROG}"' \[commit aborted\]: correct above errors first!' \
2940 "${CPROG}"' commit: nothing known about `ssfile'\''
2941 '"${CPROG}"' \[commit aborted\]: correct above errors first!'
2942
2943           dotest basica-4 "${testcvs} add ssfile" \
2944 "${SPROG}"' add: scheduling file `ssfile'\'' for addition
2945 '"${SPROG}"' add: use .'"${SPROG}"' commit. to add this file permanently'
2946           dotest_fail basica-4a "${testcvs} tag tag0 ssfile" \
2947 "${SPROG} tag: nothing known about ssfile
2948 ${SPROG} "'\[tag aborted\]: correct the above errors first!'
2949           cd ../..
2950           dotest basica-5 "${testcvs} -q ci -m add-it" \
2951 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  sdir/ssdir/ssfile
2952 initial revision: 1\.1"
2953           dotest_fail basica-5a \
2954             "${testcvs} -q tag BASE sdir/ssdir/ssfile" \
2955 "${SPROG} tag: Attempt to add reserved tag name BASE
2956 ${SPROG} \[tag aborted\]: failed to set tag BASE to revision 1\.1 in ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v"
2957           dotest basica-5b "${testcvs} -q tag NOT_RESERVED" \
2958 'T sdir/ssdir/ssfile'
2959
2960           dotest basica-6 "${testcvs} -q update" ''
2961           echo "ssfile line 2" >>sdir/ssdir/ssfile
2962           dotest_fail basica-6.2 "${testcvs} -q diff -c" \
2963 "Index: sdir/ssdir/ssfile
2964 ===================================================================
2965 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
2966 retrieving revision 1\.1
2967 diff -c -r1\.1 ssfile
2968 \*\*\* sdir/ssdir/ssfile        ${RFCDATE}      1\.1
2969 --- sdir/ssdir/ssfile   ${RFCDATE}
2970 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
2971 \*\*\* 1 \*\*\*\*
2972 --- 1,2 ----
2973   ssfile
2974 ${PLUS} ssfile line 2"
2975           dotest_fail basica-6.3 "${testcvs} -q diff -c -rBASE" \
2976 "Index: sdir/ssdir/ssfile
2977 ===================================================================
2978 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
2979 retrieving revision 1\.1
2980 diff -c -r1\.1 ssfile
2981 \*\*\* sdir/ssdir/ssfile        ${RFCDATE}      1\.1
2982 --- sdir/ssdir/ssfile   ${RFCDATE}
2983 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
2984 \*\*\* 1 \*\*\*\*
2985 --- 1,2 ----
2986   ssfile
2987 ${PLUS} ssfile line 2"
2988           dotest_fail basica-6.4 "${testcvs} -q diff -c -rBASE -C3isacrowd" \
2989 "Index: sdir/ssdir/ssfile
2990 ===================================================================
2991 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
2992 retrieving revision 1\.1
2993 diff -c -C 3isacrowd -r1\.1 ssfile
2994 ${SPROG} diff: invalid context length argument"
2995           dotest basica-7 "${testcvs} -q ci -m modify-it" \
2996 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  sdir/ssdir/ssfile
2997 new revision: 1\.2; previous revision: 1\.1"
2998           dotest_fail basica-nonexist "${testcvs} -q ci nonexist" \
2999 "${CPROG}"' commit: nothing known about `nonexist'\''
3000 '"${CPROG}"' \[commit aborted\]: correct above errors first!'
3001           dotest basica-8 "${testcvs} -q update ." ''
3002
3003           # Test the -f option to ci
3004           cd sdir/ssdir
3005           dotest basica-8a0 "${testcvs} -q ci -m not-modified ssfile" ''
3006           dotest basica-8a "${testcvs} -q ci -f -m force-it" \
3007 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3008 new revision: 1\.3; previous revision: 1\.2"
3009           dotest basica-8a1 "${testcvs} -q ci -m bump-it -r 2.0" \
3010 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3011 new revision: 2\.0; previous revision: 1\.3"
3012           dotest basica-8a1a "${testcvs} -q ci -m bump-it -r 2.9" \
3013 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3014 new revision: 2\.9; previous revision: 2\.0"
3015           # Test string-based revion number increment rollover
3016           dotest basica-8a1b "${testcvs} -q ci -m bump-it -f -r 2" \
3017 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3018 new revision: 2\.10; previous revision: 2\.9"
3019           dotest basica-8a1c "${testcvs} -q ci -m bump-it -r 2.99" \
3020 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3021 new revision: 2\.99; previous revision: 2\.10"
3022           # Test string-based revion number increment rollover
3023           dotest basica-8a1d "${testcvs} -q ci -m bump-it -f -r 2" \
3024 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3025 new revision: 2\.100; previous revision: 2\.99"
3026           dotest basica-8a1e "${testcvs} -q ci -m bump-it -r 2.1099" \
3027 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3028 new revision: 2\.1099; previous revision: 2\.100"
3029           # Test string-based revion number increment rollover
3030           dotest basica-8a1f "${testcvs} -q ci -m bump-it -f -r 2" \
3031 "${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3032 new revision: 2\.1100; previous revision: 2\.1099"
3033           # -f should not be necessary, but it should be harmless.
3034           # Also test the "-r 3" (rather than "-r 3.0") usage.
3035           dotest basica-8a2 "${testcvs} -q ci -m bump-it -f -r 3" \
3036 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3037 new revision: 3\.1; previous revision: 2\.1100"
3038
3039           # Test using -r to create a branch
3040           dotest_fail basica-8a3 "${testcvs} -q ci -m bogus -r 3.0.0" \
3041 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3042 $SPROG commit: $CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v: can't find branch point 3\.0
3043 $SPROG commit: could not check in ssfile"
3044           dotest basica-8a4 "${testcvs} -q ci -m valid -r 3.1.2" \
3045 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3046 new revision: 3\.1\.2\.1; previous revision: 3\.1"
3047           # now get rid of the sticky tag and go back to the trunk
3048           dotest basica-8a5 "${testcvs} -q up -A ./" "[UP] ssfile"
3049
3050           cd ../..
3051           dotest basica-8b "${testcvs} -q diff -r1.2 -r1.3"
3052
3053           dotest basica-8b1 "${testcvs} -q diff -r1.2 -r1.3 -C 3isacrowd"
3054
3055           # The .* here will normally be "No such file or directory",
3056           # but if memory serves some systems (AIX?) have a different message.
3057 :         dotest_fail basica-9 \
3058             "${testcvs} -q -d ${TESTDIR}/nonexist update" \
3059 "${SPROG}: cannot access cvs root ${TESTDIR}/nonexist: .*"
3060           dotest_fail basica-9a \
3061             "${testcvs} -q -d ${TESTDIR}/nonexist update" \
3062 "${CPROG} \[update aborted\]: ${TESTDIR}/nonexist/CVSROOT: .*"
3063
3064           dotest basica-10 "${testcvs} annotate" \
3065 '
3066 Annotations for sdir/ssdir/ssfile
3067 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
3068 1\.1          .'"$username8"' *[0-9a-zA-Z-]*.: ssfile
3069 1\.2          .'"$username8"' *[0-9a-zA-Z-]*.: ssfile line 2'
3070
3071           # Test resurrecting with strange revision numbers
3072           cd sdir/ssdir
3073           dotest basica-r1 "${testcvs} rm -f ssfile" \
3074 "${SPROG} remove: scheduling .ssfile. for removal
3075 ${SPROG} remove: use .${SPROG} commit. to remove this file permanently"
3076           dotest basica-r2 "${testcvs} -q ci -m remove" \
3077 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3078 new revision: delete; previous revision: 3\.1"
3079           dotest basica-r3 "${testcvs} -q up -p -r 3.1 ./ssfile >ssfile" ""
3080           dotest basica-r4 "${testcvs} add ssfile" \
3081 "${SPROG} add: Re-adding file .ssfile. after dead revision 3\.2\.
3082 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3083           dotest basica-r5 "${testcvs} -q ci -m resurrect" \
3084 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  ssfile
3085 new revision: 3\.3; previous revision: 3\.2"
3086           cd ../..
3087
3088           # As long as we have a file with a few revisions, test
3089           # a few "cvs admin -o" invocations.
3090           cd sdir/ssdir
3091           dotest_fail basica-o1 "${testcvs} admin -o 1.2::1.2" \
3092 "${CPROG} admin: while processing more than one file:
3093 ${CPROG} \[admin aborted\]: attempt to specify a numeric revision"
3094           dotest basica-o2 "${testcvs} admin -o 1.2::1.2 ssfile" \
3095 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3096 done"
3097           dotest basica-o2a "${testcvs} admin -o 1.1::NOT_RESERVED ssfile" \
3098 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3099 done"
3100           dotest_fail basica-o2b "${testcvs} admin -o 1.1::NOT_EXIST ssfile" \
3101 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3102 ${SPROG} admin: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v: Revision NOT_EXIST doesn't exist.
3103 ${SPROG} admin: RCS file for .ssfile. not modified\."
3104           dotest basica-o3 "${testcvs} admin -o 1.2::1.3 ssfile" \
3105 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3106 done"
3107           dotest basica-o4 "${testcvs} admin -o 3.1:: ssfile" \
3108 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3109 deleting revision 3\.3
3110 deleting revision 3\.2
3111 done"
3112           dotest basica-o5 "${testcvs} admin -o ::1.1 ssfile" \
3113 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3114 done"
3115           dotest basica-o5a "${testcvs} -n admin -o 1.2::3.1 ssfile" \
3116 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3117 deleting revision 2\.1100
3118 deleting revision 2\.1099
3119 deleting revision 2\.100
3120 deleting revision 2\.99
3121 deleting revision 2\.10
3122 deleting revision 2\.9
3123 deleting revision 2\.0
3124 deleting revision 1\.3
3125 done"
3126           dotest basica-o6 "${testcvs} admin -o 1.2::3.1 ssfile" \
3127 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3128 deleting revision 2\.1100
3129 deleting revision 2\.1099
3130 deleting revision 2\.100
3131 deleting revision 2\.99
3132 deleting revision 2\.10
3133 deleting revision 2\.9
3134 deleting revision 2\.0
3135 deleting revision 1\.3
3136 done"
3137           dotest basica-o6a "${testcvs} admin -o 3.1.2: ssfile" \
3138 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3139 deleting revision 3\.1\.2\.1
3140 done"
3141           dotest basica-o7 "${testcvs} log -N ssfile" "
3142 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
3143 Working file: ssfile
3144 head: 3\.1
3145 branch:
3146 locks: strict
3147 access list:
3148 keyword substitution: kv
3149 total revisions: 3;     selected revisions: 3
3150 description:
3151 ----------------------------
3152 revision 3\.1
3153 date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}0 -0;  commitid: ${commitid};
3154 bump-it
3155 ----------------------------
3156 revision 1\.2
3157 date: ${ISO8601DATE};  author: ${username};  state: Exp;  lines: ${PLUS}1 -0;  commitid: ${commitid};
3158 modify-it
3159 ----------------------------
3160 revision 1\.1
3161 date: ${ISO8601DATE};  author: ${username};  state: Exp;  commitid: ${commitid};
3162 add-it
3163 ============================================================================="
3164           dotest basica-o8 "${testcvs} -q update -p -r 1.1 ./ssfile" "ssfile"
3165           cd ../..
3166
3167           cd ..
3168
3169           modify_repo rm -rf $CVSROOT_DIRNAME/first-dir
3170           rm -r first-dir
3171           ;;
3172
3173
3174
3175         basicb)
3176           # More basic tests, including non-branch tags and co -d.
3177           mkdir 1; cd 1
3178           dotest basicb-0a "${testcvs} -q co -l ." ''
3179           touch topfile
3180           dotest basicb-0b "${testcvs} add topfile" \
3181 "${SPROG} add: scheduling file .topfile. for addition
3182 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3183           dotest basicb-0c "${testcvs} -q ci -m add-it topfile" \
3184 "$CVSROOT_DIRNAME/topfile,v  <--  topfile
3185 initial revision: 1\.1"
3186           cd ..
3187           rm -r 1
3188           mkdir 2; cd 2
3189           dotest basicb-0d "${testcvs} -q co -l ." "U topfile"
3190           # Now test the ability to run checkout on an existing working
3191           # directory without having it lose its mind.  I don't know
3192           # whether this is tested elsewhere in sanity.sh.  A more elaborate
3193           # test might also have modified files, make sure it works if
3194           # the modules file was modified to add new directories to the
3195           # module, and such.
3196           dotest basicb-0d0 "${testcvs} -q co -l ." ""
3197           mkdir first-dir
3198           dotest basicb-0e "${testcvs} add first-dir" \
3199 "Directory ${CVSROOT_DIRNAME}/first-dir put under version control"
3200           cd ..
3201           rm -r 2
3202
3203           dotest basicb-1 "${testcvs} -q co first-dir" ''
3204
3205           # The top-level CVS directory is not created by default.
3206           # I'm leaving basicb-1a and basicb-1b untouched, mostly, in
3207           # case we decide that the default should be reversed...
3208
3209           dotest_fail basicb-1a "test -d CVS" ''
3210
3211           dotest basicb-1c "cat first-dir/CVS/Repository" "first-dir"
3212
3213           cd first-dir
3214           # Note that the name Emptydir is chosen to test that CVS just
3215           # treats it like any other directory name.  It should be
3216           # special only when it is directly in $CVSROOT/CVSROOT.
3217           mkdir Emptydir sdir2
3218           dotest basicb-2 "${testcvs} add Emptydir sdir2" \
3219 "Directory ${CVSROOT_DIRNAME}/first-dir/Emptydir put under version control
3220 Directory ${CVSROOT_DIRNAME}/first-dir/sdir2 put under version control"
3221           cd Emptydir
3222           echo sfile1 starts >sfile1
3223           dotest basicb-2a10 "${testcvs} -n add sfile1" \
3224 "${SPROG} add: scheduling file .sfile1. for addition
3225 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3226           dotest basicb-2a11 "${testcvs} status sfile1" \
3227 "${SPROG} status: use \`${SPROG} add' to create an entry for \`sfile1'
3228 ===================================================================
3229 File: sfile1            Status: Unknown
3230
3231    Working revision:    No entry for sfile1
3232    Repository revision: No revision control file"
3233           dotest basicb-3 "${testcvs} add sfile1" \
3234 "${SPROG} add: scheduling file .sfile1. for addition
3235 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3236           dotest basicb-3a1 "${testcvs} status sfile1" \
3237 "===================================================================
3238 File: sfile1            Status: Locally Added
3239
3240    Working revision:    New file!
3241    Repository revision: No revision control file
3242    Sticky Tag:          (none)
3243    Sticky Date:         (none)
3244    Sticky Options:      (none)"
3245
3246           cd ../sdir2
3247           echo sfile2 starts >sfile2
3248           dotest basicb-4 "${testcvs} add sfile2" \
3249 "${SPROG} add: scheduling file .sfile2. for addition
3250 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3251           dotest basicb-4a "${testcvs} -q ci CVS" \
3252 "${CPROG} commit: warning: directory CVS specified in argument
3253 ${CPROG} commit: but CVS uses CVS for its own purposes; skipping CVS directory"
3254           cd ..
3255           dotest basicb-5 "${testcvs} -q ci -m add" \
3256 "$CVSROOT_DIRNAME/first-dir/Emptydir/sfile1,v  <--  Emptydir/sfile1
3257 initial revision: 1\.1
3258 $CVSROOT_DIRNAME/first-dir/sdir2/sfile2,v  <--  sdir2/sfile2
3259 initial revision: 1\.1"
3260           echo sfile1 develops >Emptydir/sfile1
3261           dotest basicb-6 "${testcvs} -q ci -m modify" \
3262 "$CVSROOT_DIRNAME/first-dir/Emptydir/sfile1,v  <--  Emptydir/sfile1
3263 new revision: 1\.2; previous revision: 1\.1"
3264           dotest basicb-7 "${testcvs} -q tag release-1" 'T Emptydir/sfile1
3265 T sdir2/sfile2'
3266           echo not in time for release-1 >sdir2/sfile2
3267           dotest basicb-8 "${testcvs} -q ci -m modify-2" \
3268 "$CVSROOT_DIRNAME/first-dir/sdir2/sfile2,v  <--  sdir2/sfile2
3269 new revision: 1\.2; previous revision: 1\.1"
3270           # See if CVS can correctly notice when an invalid numeric
3271           # revision is specified.
3272           # Commented out until we get around to fixing CVS
3273 :         dotest basicb-8a0 "${testcvs} diff -r 1.5 -r 1.7 sfile2" 'error msg'
3274           cd ..
3275
3276           # Test that we recurse into the correct directory when checking
3277           # for existing files, even if co -d is in use.
3278           touch first-dir/extra
3279           dotest basicb-cod-1 "${testcvs} -q co -d first-dir1 first-dir" \
3280 'U first-dir1/Emptydir/sfile1
3281 U first-dir1/sdir2/sfile2'
3282           rm -r first-dir1
3283
3284           rm -r first-dir
3285
3286           # FIXME? basicb-9 used to check things out like this:
3287           #   U newdir/Emptydir/sfile1
3288           #   U newdir/sdir2/sfile2
3289           # but that's difficult to do.  The whole "shorten" thing
3290           # is pretty bogus, because it will break on things
3291           # like "cvs co foo/bar baz/quux".  Unless there's some
3292           # pretty detailed expansion and analysis of the command-line
3293           # arguments, we shouldn't do "shorten" stuff at all.
3294
3295           dotest basicb-9 \
3296 "${testcvs} -q co -d newdir -r release-1 first-dir/Emptydir first-dir/sdir2" \
3297 'U newdir/first-dir/Emptydir/sfile1
3298 U newdir/first-dir/sdir2/sfile2'
3299
3300           # basicb-9a and basicb-9b: see note about basicb-1a
3301
3302           dotest_fail basicb-9a "test -d CVS" ''
3303
3304           dotest basicb-9c "cat newdir/CVS/Repository" "\."
3305           dotest basicb-9d "cat newdir/first-dir/CVS/Repository" \
3306 "${CVSROOT_DIRNAME}/first-dir" \
3307 "first-dir"
3308           dotest basicb-9e "cat newdir/first-dir/Emptydir/CVS/Repository" \
3309 "${CVSROOT_DIRNAME}/first-dir/Emptydir" \
3310 "first-dir/Emptydir"
3311           dotest basicb-9f "cat newdir/first-dir/sdir2/CVS/Repository" \
3312 "${CVSROOT_DIRNAME}/first-dir/sdir2" \
3313 "first-dir/sdir2"
3314
3315           dotest basicb-10 "cat newdir/first-dir/Emptydir/sfile1 newdir/first-dir/sdir2/sfile2" \
3316 "sfile1 develops
3317 sfile2 starts"
3318
3319           rm -r newdir
3320
3321           # Hmm, this might be a case for CVSNULLREPOS, but CVS doesn't
3322           # seem to deal with it...
3323           if false; then
3324           dotest basicb-11 "${testcvs} -q co -d sub1/sub2 first-dir" \
3325 "U sub1/sub2/Emptydir/sfile1
3326 U sub1/sub2/sdir2/sfile2"
3327           cd sub1
3328           dotest basicb-12 "${testcvs} -q update ./." ''
3329           touch xx
3330           dotest basicb-13 "${testcvs} add xx" fixme
3331           cd ..
3332           rm -r sub1
3333           # to test: sub1/sub2/sub3
3334           fi # end of tests commented out.
3335
3336           # Create a second directory.
3337           mkdir 1
3338           cd 1
3339           dotest basicb-14 "${testcvs} -q co -l ." 'U topfile'
3340           mkdir second-dir
3341           dotest basicb-15 "${testcvs} add second-dir" \
3342 "Directory ${CVSROOT_DIRNAME}/second-dir put under version control"
3343           cd second-dir
3344           touch aa
3345           dotest basicb-16 "${testcvs} add aa" \
3346 "${SPROG} add: scheduling file .aa. for addition
3347 ${SPROG} add: use .${SPROG} commit. to add this file permanently"
3348           dotest basicb-17 "${testcvs} -q ci -m add" \
3349 "$CVSROOT_DIRNAME/second-dir/aa,v  <--  aa
3350 initial revision: 1\.1"
3351           cd ..
3352
3353           # Try to remove all revisions in a file.
3354           dotest_fail basicb-o1 "${testcvs} admin -o1.1 topfile" \
3355 "RCS file: ${CVSROOT_DIRNAME}/topfile,v
3356 deleting revision 1\.1
3357 ${SPROG} \[admin aborted\]: attempt to delete all revisions"
3358           dotest basicb-o2 "${testcvs} -q update -d first-dir" \
3359 "U first-dir/Emptydir/sfile1
3360 U first-dir/sdir2/sfile2"
3361           dotest_fail basicb-o3 \
3362 "${testcvs} admin -o1.1:1.2 first-dir/sdir2/sfile2" \
3363 "RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v
3364 deleting revision 1\.2
3365 deleting revision 1\.1
3366 ${SPROG} \[admin aborted\]: attempt to delete all revisions"
3367           cd ..
3368           rm -r 1
3369
3370           mkdir 1; cd 1
3371           # Note that -H is an invalid option.
3372           # I suspect that the choice between "illegal" and "invalid"
3373           # depends on the user's environment variables, the phase
3374           # of the moon (weirdness with optind), and who knows what else.
3375           # I've been seeing "illegal"...
3376           # And I switched it to "invalid". -DRP
3377           # POSIX 1003.2 specifies the format should be 'illegal option'
3378           # many other folks are still using the older 'invalid option'
3379           # lib/getopt.c will use POSIX when __posixly_correct
3380           # otherwise the other, so accept both of them. -- mdb
3381           # Added optional single quotes. -- mirabilos
3382           # The above is actually untrue, POSIX only documents some older
3383           # texts that can be used and explicitly leaves open the format
3384           # of these messages. Also, GNU getopt is broken and does not
3385           # use __progname in the first place. *sigh* -- mirabilos
3386           dotest_fail basicb-21 "${testcvs} -q admin -H" \
3387 "admin: invalid option -- '*H'*
3388 ${CPROG} \[admin aborted\]: specify ${CPROG} -H admin for usage information" \
3389 "cvs: illegal option -- '*H'*
3390 ${CPROG} \[admin aborted\]: specify ${CPROG} -H admin for usage information"
3391           cd ..
3392           rmdir 1
3393
3394           if $keep; then
3395             echo Keeping ${TESTDIR} and exiting due to --keep
3396             exit 0
3397           fi
3398
3399           modify_repo rm -rf $CVSROOT_DIRNAME/first-dir \
3400                              $CVSROOT_DIRNAME/second-dir
3401           modify_repo rm -f $CVSROOT_DIRNAME/topfile,v
3402           ;;
3403
3404
3405
3406         basicc)
3407           # More tests of basic/miscellaneous functionality.
3408           mkdir 1; cd 1
3409           dotest_fail basicc-1 "$testcvs diff" \
3410 "$CPROG diff: in directory \.:
3411 $CPROG \[diff aborted\]: there is no version here; run .$CPROG checkout. first"
3412           dotest basicc-2 "$testcvs -q co -l ."
3413           mkdir first-dir second-dir
3414           dotest basicc-3 "${testcvs} add first-dir second-dir" \
3415 "Directory ${CVSROOT_DIRNAME}/first-dir put under version control
3416 Directory ${CVSROOT_DIRNAME}/second-dir put under version control"
3417           # Old versions of CVS often didn't create this top-level CVS
3418           # directory in the first place.  I think that maybe the only
3419           # way to get it to work currently is to let CVS create it,
3420           # and then blow it away (don't complain if it does not
3421           # exist).  But that is perfectly valid; people who are used
3422           # to the old behavior especially may be interested.
3423           # FIXME: this test is intended for the TopLevelAdmin=yes case;
3424           # should adjust/move