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