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