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