1#!/bin/sh
2#
3# Copyright (c) 2010 Advanced Computing Technologies LLC
4# Written by: John H. Baldwin <jhb@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28# $FreeBSD$
29
30# Various regression tests to run for the 'update' command.
31
32WORKDIR=work
33
34usage()
35{
36	echo "Usage: tests.sh [-w workdir]"
37	exit 1
38}
39
40# Allow the user to specify an alternate work directory.
41while getopts "w:" option; do
42	case $option in
43		w)
44			WORKDIR=$OPTARG
45			;;
46		*)
47			echo
48			usage
49			;;
50	esac
51done
52shift $((OPTIND - 1))
53if [ $# -ne 0 ]; then
54	usage
55fi
56
57CONFLICTS=$WORKDIR/conflicts
58OLD=$WORKDIR/old
59NEW=$WORKDIR/current
60TEST=$WORKDIR/test
61
62# The various states of the comparison of a file between two trees.
63states="equal first second difftype difflinks difffiles"
64
65build_trees()
66{
67	local i j k
68
69	rm -rf $OLD $NEW $TEST $CONFLICTS
70	mkdir -p $OLD/etc $NEW/etc $TEST/etc
71
72	# For an given file, there are three different pair-wise
73	# relations between the three threes (old, new, and test): old
74	# vs new, old vs test, and new vs test.  Each of these
75	# relations takes on one of six different states from the
76	# 'compare()' function in etcupdate: equal, onlyfirst,
77	# onlysecond, difftype, difflinks, difffiles.  In addition,
78	# there are special considerations for considering cases such
79	# as a file merge that results in conflicts versus one that
80	# does not, special treatment of directories, etc.  The tests
81	# below attempt to enumerate the three dimensional test matrix
82	# by having the path name use the three different tree states
83	# for the parent directories.
84	#
85	# Note that if the old and new files are identical (so first
86	# compare is "equal"), then the second and third comparisons
87	# will be the same.
88	#
89	# Note also that etcupdate only cares about files that are
90	# present in at least one of the old or new trees.  Thus, none
91	# of the '*/second/second' cases are relevant.
92
93	for i in $states; do
94		for j in $states; do
95			for k in $states; do
96				mkdir -p $OLD/$i/$j/$k $NEW/$i/$j/$k \
97				    $TEST/$i/$j/$k
98			done
99		done
100	done
101
102	# /equal/equal/equal: Everything is equal.  Nothing should happen.
103	for i in $OLD $NEW $TEST; do
104		mkfifo $i/equal/equal/equal/fifo
105		echo "foo" > $i/equal/equal/equal/file
106		mkdir $i/equal/equal/equal/dir
107		ln -s "bar" $i/equal/equal/equal/link
108	done
109
110	# /equal/first/first: The file is missing from the test
111	# directory.  Nothing should happen.
112	for i in $OLD $NEW; do
113		mkfifo $i/equal/first/first/fifo
114		echo "foo" > $i/equal/first/first/file
115		mkdir $i/equal/first/first/dir
116		ln -s "bar" $i/equal/first/first/link
117	done
118
119	# /equal/difftype/difftype: The local file is a different
120	# type.  Nothing should happen.
121	for i in $OLD $NEW; do
122		mkfifo $i/equal/difftype/difftype/fifo
123		mkdir $i/equal/difftype/difftype/fromdir
124	done
125	echo "bar" > $TEST/equal/difftype/difftype/fifo
126	ln -s "test" $TEST/equal/difftype/difftype/fromdir
127
128	# /equal/difflinks/difflinks: The local file is a modified
129	# link. Nothing should happen.
130	for i in $OLD $NEW; do
131		ln -s "foo" $i/equal/difflinks/difflinks/link
132	done
133	ln -s "bar" $TEST/equal/difflinks/difflinks/link
134
135	# /equal/difffiles/difffiles: The local file is a modified
136	# file.  Nothing should happen.
137	for i in $OLD $NEW; do
138		echo "foo" > $i/equal/difffiles/difffiles/file
139	done
140	echo "bar" > $TEST/equal/difffiles/difffiles/file
141
142	# /first/equal/second: Remove unmodified files.  The files
143	# should all be removed.
144	for i in $OLD $TEST; do
145		mkfifo $i/first/equal/second/fifo
146		echo "foo" > $i/first/equal/second/file
147		mkdir $i/first/equal/second/emptydir
148		ln -s "bar" $i/first/equal/second/link
149		mkdir $i/first/equal/second/fulldir
150		echo "foo" > $i/first/equal/second/fulldir/file
151	done
152
153	# /first/equal/*: Cannot occur.  If the file is missing from
154	# new, then new vs test will always be 'second'.
155
156	# /first/first/equal: Removed files are already removed.
157	# Nothing should happen.
158	mkfifo $OLD/first/first/equal/fifo
159	echo "foo" > $OLD/first/first/equal/file
160	mkdir $OLD/first/first/equal/dir
161	ln -s "bar" $OLD/first/first/equal/link
162
163	# /first/first/*: Cannot occur.  The files are missing from
164	# both new and test.
165
166	# /first/second/*: Cannot happen, if the file is in old for
167	# old vs new, it cannot be missing for old vs test.
168
169	# /first/difftype/second: File with different local type
170	# removed.  Should generate a warning.
171	mkfifo $OLD/first/difftype/second/fifo
172	mkdir $TEST/first/difftype/second/fifo
173
174	# /first/difftype/*: Cannot happen since the file is missing
175	# from new but present in test.
176
177	# /first/difflinks/second: Modified link removed.  Should
178	# generate a warning.
179	ln -s "old link" $OLD/first/difflinks/second/link
180	ln -s "test link" $TEST/first/difflinks/second/link
181
182	# /first/difflinks/*: Cannot happen since the file is missing
183	# from new but present in test.
184
185	# /first/difffiles/second: Modified file removed.  Should
186	# generate a warning.
187	echo "foo" > $OLD/first/difffiles/second/file
188	echo "bar" > $TEST/first/difffiles/second/file
189
190	# /first/difffiles/*: Cannot happen since the file is missing
191	# from new but present in test.
192
193	# /second/equal/first: Added a new file that isn't present in
194	# test.  The empty directory should be ignored.
195	echo "bar" > $NEW/second/equal/first/file
196	mkfifo $NEW/second/equal/first/fifo
197	ln -s "new" $NEW/second/equal/first/link
198	mkdir $NEW/second/equal/first/emptydir
199	mkdir $NEW/second/equal/first/fulldir
200	echo "foo" > $NEW/second/equal/first/fulldir/file
201
202	# /second/equal/*: Cannot happen since the file is missing
203	# from test but present in new.
204
205	# /second/first/*: Cannot happen since the file is missing
206	# from old.
207
208	# /second/second/equal: Newly added file is already present in
209	# the test directory and identical to the new file.  Nothing
210	# should happen.
211	for i in $NEW $TEST; do
212		mkfifo $i/second/second/equal/fifo
213		echo "foo" > $i/second/second/equal/file
214		mkdir $i/second/second/equal/dir
215		ln -s "bar" $i/second/second/equal/link
216	done
217
218	# /second/second/first: Cannot happen.  The file is in dest in
219	# the second test, so it can't be missing from the third test.
220
221	# /second/second/second: Cannot happen.  The file is in new in
222	# the first test, so it can't be missing from the third test.
223
224	# /second/second/difftype: Newly added file conflicts with
225	# existing file in test tree of a different type.  Should
226	# generate a warning.
227	mkdir $NEW/second/second/difftype/dir
228	mkfifo $TEST/second/second/difftype/dir
229
230	# /second/second/difflinks: Newly added link conflicts with
231	# existing link in test tree.  Should generate a warning.
232	ln -s "new link" $NEW/second/second/difflinks/link
233	ln -s "test link" $TEST/second/second/difflinks/link
234
235	# /second/second/difffiles: Newly added file conflicts with
236	# existing file in test tree.  Should generate a warning.
237	echo "new" > $NEW/second/second/difffiles/file
238	echo "test" > $TEST/second/second/difffiles/file
239
240	# /second/difftype/*: Cannot happen since the file is missing
241	# from old.
242
243	# /second/difflinks/*: Cannot happen since the file is missing
244	# from old.
245
246	# /second/difffiles/*: Cannot happen since the file is missing
247	# from old.
248
249	# /difftype/equal/difftype: Unmodified file has changed type.
250	# File should be updated to the new file.  In the 'todir' case
251	# the directory won't actually be created because it is empty.
252	for i in $OLD $TEST; do
253		echo "foo" > $i/difftype/equal/difftype/file
254		mkdir $i/difftype/equal/difftype/fromdir
255		ln -s "old" $i/difftype/equal/difftype/todir
256	done
257	ln -s "test" $NEW/difftype/equal/difftype/file
258	mkfifo $NEW/difftype/equal/difftype/fromdir
259	mkdir $NEW/difftype/equal/difftype/todir
260
261	# /difftype/equal/*: Cannot happen.  Since the old file is a
262	# difftype from the new file and the test file is identical to
263	# the old file, the test file must be a difftype from the new
264	# file.
265
266	# /difftype/first/first: A removed file has changed type.
267	# This should generate a warning.
268	mkfifo $OLD/difftype/first/first/fifo
269	mkdir $NEW/difftype/first/first/fifo
270
271	# /difftype/first/*: Cannot happen.  Since the new file exists
272	# and the dest file is missing, the last test must be 'first'.
273
274	# /difftype/second/*: Cannot happen.  The old file exists in
275	# the first test, so it cannot be missing in the second test.
276
277	# /difftype/difftype/equal: A file has changed type, but the
278	# file in the test directory already matches the new file.  Do
279	# nothing.
280	echo "foo" > $OLD/difftype/difftype/equal/fifo
281	mkfifo $OLD/difftype/difftype/equal/file
282	for i in $NEW $TEST; do
283		mkfifo $i/difftype/difftype/equal/fifo
284		echo "bar" > $i/difftype/difftype/equal/file
285	done
286
287	# /difftype/difftype/first: Cannot happen.  The dest file
288	# exists in the second test.
289
290	# /difftype/difftype/second: Cannot happen.  The new file
291	# exists in the first test.
292
293	# /difftype/difftype/difftype: All three files (old, new, and
294	# test) are different types from each other.  This should
295	# generate a warning.
296	mkfifo $OLD/difftype/difftype/difftype/one
297	mkdir $NEW/difftype/difftype/difftype/one
298	echo "foo" > $TEST/difftype/difftype/difftype/one
299	mkdir $OLD/difftype/difftype/difftype/two
300	echo "baz" > $NEW/difftype/difftype/difftype/two
301	ln -s "bar" $TEST/difftype/difftype/difftype/two
302
303	# /difftype/difftype/difflinks: A file has changed from a
304	# non-link to a link in both the new and test trees, but the
305	# target of the new and test links differ.  This should
306	# generate a new link conflict.
307	mkfifo $OLD/difftype/difftype/difflinks/link
308	ln -s "new" $NEW/difftype/difftype/difflinks/link
309	ln -s "test" $TEST/difftype/difftype/difflinks/link
310
311	# /difftype/difftype/difffile: A file has changed from a
312	# non-regular file to a regular file in both the new and test
313	# trees, but the contents in the new and test files differ.
314	# This should generate a new file conflict.
315	ln -s "old" $OLD/difftype/difftype/difffiles/file
316	echo "foo" > $NEW/difftype/difftype/difffiles/file
317	echo "bar" > $TEST/difftype/difftype/difffiles/file
318
319	# /difflinks/equal/difflinks: An unmodified symlink has
320	# changed.  The link should be updated.
321	for i in $OLD $TEST; do
322		ln -s "old" $i/difflinks/equal/difflinks/link
323	done
324	ln -s "new" $NEW/difflinks/equal/difflinks/link
325
326	# /difflinks/equal/*: Cannot happen.  Since old is identical
327	# to test, the third test must be 'difflinks'.
328
329	# /difflinks/first/first: A modified link is missing in the
330	# test tree.  This should generate a warning.
331	ln -s "old" $OLD/difflinks/first/first/link
332	ln -s "new" $NEW/difflinks/first/first/link
333
334	# /difflinks/first/*: Cannot happen.  Since the test file is
335	# missing in the second test, it must be missing in the third
336	# test.
337
338	# /difflinks/second/*: Cannot happen.  The old link is present
339	# in the first test, so it cannot be missing in the second
340	# test.
341
342	# /difflinks/difftype/difftype: An updated link has been
343	# changed to a different file type in the test tree.  This
344	# should generate a warning.
345	ln -s "old" $OLD/difflinks/difftype/difftype/link
346	ln -s "new" $NEW/difflinks/difftype/difftype/link
347	echo "test" > $TEST/difflinks/difftype/difftype/link
348
349	# /difflinks/difftype/*: Cannot happen.  The old and new files
350	# are both links and the test file is not a link, so the third
351	# test must be 'difftype'.
352
353	# /difflinks/difflinks/equal: An updated link has already been
354	# updated to the new target in the test tree.  Nothing should
355	# happen.
356	ln -s "old" $OLD/difflinks/difflinks/equal/link
357	for i in $NEW $TEST; do
358		ln -s "new" $i/difflinks/difflinks/equal/link
359	done
360
361	# /difflinks/difflinks/difflinks: An updated link has been
362	# modified in the test tree and doesn't match either the old
363	# or new links.  This should generate a warning.
364	ln -s "old" $OLD/difflinks/difflinks/difflinks/link
365	ln -s "new" $NEW/difflinks/difflinks/difflinks/link
366	ln -s "test" $TEST/difflinks/difflinks/difflinks/link
367
368	# /difflinks/difflinks/*: Cannot happen.  All three files are
369	# links from the first two tests, so the third test can only
370	# be 'equal' or 'difflink'.
371
372	# /difflinks/difffiles/*: Cannot happen.  The old file is a
373	# link in the first test, so it cannot be a regular file in
374	# the second.
375
376	# /difffiles/equal/difffiles: An unmodified file has been
377	# changed in new tree.  The file should be updated to the new
378	# version.
379	for i in $OLD $TEST; do
380		echo "foo" > $i/difffiles/equal/difffiles/file
381	done
382	echo "bar" > $NEW/difffiles/equal/difffiles/file
383
384	# /difffiles/equal/*: Cannot happen.  Since the old file is
385	# identical to the test file, the third test must be
386	# 'difffiles'.
387
388	# /difffiles/first/first: A removed file has been changed in
389	# the new tree.  This should generate a warning.
390	echo "foo" > $OLD/difffiles/first/first/file
391	echo "bar" > $NEW/difffiles/first/first/file
392
393	# /difffiles/first/*: Cannot happen.  The new file is a
394	# regular file from the first test and the test file is
395	# missing in the second test, so the third test must be
396	# 'first'.
397
398	# /difffiles/second/*: Cannot happen.  The old file is present
399	# in the first test, so it must be present in the second test.
400
401	# /difffiles/difftype/difftype: An updated regular file has
402	# been changed to a different file type in the test tree.
403	# This should generate a warning.
404	echo "old" > $OLD/difffiles/difftype/difftype/file
405	echo "new" > $NEW/difffiles/difftype/difftype/file
406	mkfifo $TEST/difffiles/difftype/difftype/file
407
408	# /difffiles/difftype/*: Cannot happen.  The new file is known
409	# to be a regular file from the first test, and the test file
410	# is known to exist as a different file type from the second
411	# test.  The third test must be 'difftype'.
412
413	# /difffiles/difflink/*: Cannot happen.  The old file is known
414	# to be a regular file from the first test, so it cannot be a
415	# link in the second test.
416
417	# /difffiles/difffiles/equal: An updated regular file has
418	# already been updated to match the new file in the test tree.
419	# Nothing should happen.
420	echo "foo" > $OLD/difffiles/difffiles/equal/file
421	for i in $NEW $TEST; do
422		echo "bar" > $i/difffiles/difffiles/equal/file
423	done
424
425	# /difffiles/difffiles/difffiles: A modified regular file was
426	# updated in the new tree.  The changes should be merged into
427	# to the new file if possible.  If the merge fails, a conflict
428	# should be generated.
429	cat > $OLD/difffiles/difffiles/difffiles/simple <<EOF
430this is an old line
431
432EOF
433	cat > $NEW/difffiles/difffiles/difffiles/simple <<EOF
434this is a new line
435
436EOF
437	cat > $TEST/difffiles/difffiles/difffiles/simple <<EOF
438this is an old line
439
440this is a local line
441EOF
442	cat > $OLD/difffiles/difffiles/difffiles/conflict <<EOF
443this is an old file
444EOF
445	cat > $NEW/difffiles/difffiles/difffiles/conflict <<EOF
446this is a new file
447EOF
448	cat > $TEST/difffiles/difffiles/difffiles/conflict <<EOF
449this is a test file
450EOF
451
452	# /difffiles/difffiles/*: Cannot happen.  From the first three
453	# tests, all three files are regular files.  The test file can
454	# either be identical to the new file ('equal') or not
455	# ('difffiles').
456
457	## Tests for adding directories
458	mkdir -p $OLD/adddir $NEW/adddir $TEST/adddir
459
460	# /adddir/conflict: Add a new file in a directory that already
461	# exists as a file.  This should generate two warnings.
462	mkdir $NEW/adddir/conflict
463	touch $NEW/adddir/conflict/newfile
464	touch $TEST/adddir/conflict
465
466	# /adddir/partial: Add a new file in a directory.  The
467	# directory already exists in the test tree and contains a
468	# different local file.  The new file from the new tree should
469	# be added.
470	for i in $NEW $TEST; do
471		mkdir $i/adddir/partial
472	done
473	echo "foo" > $NEW/adddir/partial/file
474	mkfifo $TEST/adddir/partial/fifo
475
476	## Tests for removing directories
477	mkdir -p $OLD/rmdir $NEW/rmdir $TEST/rmdir
478
479	# /rmdir/extra: Do not remove a directory with an extra local file.
480	# This should generate a warning.
481	for i in $OLD $TEST; do
482		mkdir $i/rmdir/extra
483	done
484	echo "foo" > $TEST/rmdir/extra/localfile.txt
485
486	# /rmdir/conflict: Do not remove a directory with a conflicted
487	# remove file.  This should generate a warning.
488	for i in $OLD $TEST; do
489		mkdir $i/rmdir/conflict
490	done
491	mkfifo $OLD/rmdir/conflict/difftype
492	mkdir $TEST/rmdir/conflict/difftype
493
494	# /rmdir/partial: Remove a complete hierarchy when part of the
495	# tree has already been removed locally.
496	for i in $OLD $TEST; do
497		mkdir -p $i/rmdir/partial/subdir
498		mkfifo $i/rmdir/partial/subdir/fifo
499	done
500	echo "foo" > $OLD/rmdir/partial/subdir/file
501
502	## Tests for converting files to directories and vice versa
503	for i in $OLD $NEW $TEST; do
504		for j in already old fromdir todir; do
505			mkdir -p $i/dirchange/$j
506		done
507	done
508
509	# /dirchange/already/fromdir: Convert a directory tree to a
510	# file without conflicts where the test tree already has the
511	# new file.  Nothing should happen.
512	mkdir $OLD/dirchange/already/fromdir
513	echo "blah" > $OLD/dirchange/already/fromdir/somefile
514	for i in $NEW $TEST; do
515		echo "bar" > $i/dirchange/already/fromdir
516	done
517
518	# /dirchange/already/todir: Convert an unmodified file to a
519	# directory tree where the test tree already has the new
520	# tree.  Nothing should happen.
521	echo "baz" > $OLD/dirchange/already/todir
522	for i in $NEW $TEST; do
523		mkdir $i/dirchange/already/todir
524		echo "blah" > $i/dirchange/already/todir/somefile
525	done
526
527	# /dirchange/old/fromdir: Convert a directory tree to a file.
528	# The old files are unmodified and should be changed to the new tree.
529	for i in $OLD $TEST; do
530		mkdir $i/dirchange/old/fromdir
531		echo "blah" > $i/dirchange/old/fromdir/somefile
532	done
533	echo "bar" > $NEW/dirchange/old/fromdir
534
535	# /dirchange/old/todir: Convert a file to a directory tree.
536	# The old file is unmodified and should be changed to the new
537	# tree.
538	for i in $OLD $TEST; do
539		echo "foo" > $i/dirchange/old/todir
540	done
541	mkdir $NEW/dirchange/old/todir
542	echo "bar" > $NEW/dirchange/old/todir/file
543
544	# /dirchange/fromdir/extradir: Convert a directory tree to a
545	# file.  The test tree includes an extra file in the directory
546	# that is not present in the old tree.  This should generate a
547	# warning.
548	for i in $OLD $TEST; do
549		mkdir $i/dirchange/fromdir/extradir
550		echo "foo" > $i/dirchange/fromdir/extradir/file
551	done
552	mkfifo $TEST/dirchange/fromdir/extradir/fifo
553	ln -s "bar" $NEW/dirchange/fromdir/extradir
554
555	# /dirchange/fromdir/conflict: Convert a directory tree to a
556	# file.  The test tree includes a local change that generates
557	# a warning and prevents the removal of the directory.
558	for i in $OLD $TEST; do
559		mkdir $i/dirchange/fromdir/conflict
560	done
561	echo "foo" > $OLD/dirchange/fromdir/conflict/somefile
562	echo "bar" > $TEST/dirchange/fromdir/conflict/somefile
563	mkfifo $NEW/dirchange/fromdir/conflict
564
565	# /dirchange/todir/difffile: Convert a file to a directory
566	# tree.  The test tree has a locally modified version of the
567	# file so that the conversion fails with a warning.
568	echo "foo" > $OLD/dirchange/todir/difffile
569	mkdir $NEW/dirchange/todir/difffile
570	echo "baz" > $NEW/dirchange/todir/difffile/file
571	echo "bar" > $TEST/dirchange/todir/difffile
572
573	# /dirchange/todir/difftype: Similar to the previous test, but
574	# the conflict is due to a change in the file type.
575	echo "foo" > $OLD/dirchange/todir/difftype
576	mkdir $NEW/dirchange/todir/difftype
577	echo "baz" > $NEW/dirchange/todir/difftype/file
578	mkfifo $TEST/dirchange/todir/difftype
579
580	## Tests for post-install actions
581
582	# - Adding /etc/master.passwd should cause pwd_mkdb to be run
583	echo "foo:*:16000:100::0:0:& user:/home/foo:/bin/tcsh" > \
584	    $NEW/etc/master.passwd
585
586	# - Verify that updating an unmodified /etc/login.conf builds
587	# /etc/login.conf.db.
588	cat > $OLD/etc/login.conf <<EOF
589default:\\
590	:passwd_format=md5:
591EOF
592	cat > $NEW/etc/login.conf <<EOF
593default:\\
594	:passwd_format=md5:\\
595	:copyright=/etc/COPYRIGHT
596EOF
597	cp $OLD/etc/login.conf $TEST/etc/login.conf
598
599	# - Verify that a merge without conflicts to /etc/mail/aliases
600	# will trigger a newaliases run request.
601	mkdir -p $OLD/etc/mail $NEW/etc/mail $TEST/etc/mail
602	cat > $OLD/etc/mail/aliases <<EOF
603# root: me@my.domain
604
605# Basic system aliases -- these MUST be present
606MAILER-DAEMON: postmaster
607postmaster: root
608EOF
609	cat > $NEW/etc/mail/aliases <<EOF
610# root: me@my.domain
611
612# Basic system aliases -- these MUST be present
613MAILER-DAEMON: postmaster
614postmaster: root
615
616# General redirections for pseudo accounts
617_dhcp:  root
618_pflogd: root
619EOF
620	cat > $TEST/etc/mail/aliases <<EOF
621root: someone@example.com
622
623# Basic system aliases -- these MUST be present
624MAILER-DAEMON: postmaster
625postmaster: root
626EOF
627}
628
629# $1 - relative path to file that should be missing from TEST
630missing()
631{
632	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
633		echo "File $1 should be missing"
634	fi
635}
636
637# $1 - relative path to file that should be present in TEST
638present()
639{
640	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
641		echo "File $1 should be present"
642	fi
643}
644
645# $1 - relative path to file that should be a fifo in TEST
646fifo()
647{
648	if ! [ -p $TEST/$1 ]; then
649		echo "File $1 should be a FIFO"
650	fi
651}
652
653# $1 - relative path to file that should be a directory in TEST
654dir()
655{
656	if ! [ -d $TEST/$1 ]; then
657		echo "File $1 should be a directory"
658	fi
659}
660
661# $1 - relative path to file that should be a symlink in TEST
662# $2 - optional value of the link
663link()
664{
665	local val
666
667	if ! [ -L $TEST/$1 ]; then
668		echo "File $1 should be a link"
669	elif [ $# -gt 1 ]; then
670		val=`readlink $TEST/$1`
671		if [ "$val" != "$2" ]; then
672			echo "Link $1 should link to \"$2\""
673		fi
674	fi
675}
676
677# $1 - relative path to regular file that should be present in TEST
678# $2 - optional string that should match file contents
679# $3 - optional MD5 of the flie contents, overrides $2 if present
680file()
681{
682	local contents sum
683
684	if ! [ -f $TEST/$1 ]; then
685		echo "File $1 should be a regular file"
686	elif [ $# -eq 2 ]; then
687		contents=`cat $TEST/$1`
688		if [ "$contents" != "$2" ]; then
689			echo "File $1 has wrong contents"
690		fi
691	elif [ $# -eq 3 ]; then
692		sum=`md5 -q $TEST/$1`
693		if [ "$sum" != "$3" ]; then
694			echo "File $1 has wrong contents"
695		fi
696	fi
697}
698
699# $1 - relative path to a regular file that should have a conflict
700# $2 - optional MD5 of the conflict file contents
701conflict()
702{
703	local sum
704
705	if ! [ -f $CONFLICTS/$1 ]; then
706		echo "File $1 missing conflict"
707	elif [ $# -gt 1 ]; then
708		sum=`md5 -q $CONFLICTS/$1`
709		if [ "$sum" != "$2" ]; then
710			echo "Conflict $1 has wrong contents"
711		fi
712	fi
713}
714
715check_trees()
716{
717
718	echo "Checking tree for correct results:"
719
720	## /equal/equal/equal:
721	fifo /equal/equal/equal/fifo
722	file /equal/equal/equal/file "foo"
723	dir /equal/equal/equal/dir
724	link /equal/equal/equal/link "bar"
725
726	## /equal/first/first:
727	missing /equal/first/first/fifo
728	missing /equal/first/first/file
729	missing /equal/first/first/dir
730	missing /equal/first/first/link
731
732	## /equal/difftype/difftype:
733	file /equal/difftype/difftype/fifo "bar"
734	link /equal/difftype/difftype/fromdir "test"
735
736	## /equal/difflinks/difflinks:
737	link /equal/difflinks/difflinks/link "bar"
738
739	## /equal/difffiles/difffiles:
740	file /equal/difffiles/difffiles/file "bar"
741
742	## /first/equal/second:
743	missing /first/equal/second/fifo
744	missing /first/equal/second/file
745	missing /first/equal/second/emptydir
746	missing /first/equal/second/link
747	missing /first/equal/second/fulldir
748
749	## /first/first/equal:
750	missing /first/first/equal/fifo
751	missing /first/first/equal/file
752	missing /first/first/equal/dir
753	missing /first/first/equal/link
754
755	## /first/difftype/second:
756	present /first/difftype/second/fifo
757
758	## /first/difflinks/second:
759	link /first/difflinks/second/link "test link"
760
761	## /first/difffiles/second:
762	file /first/difffiles/second/file "bar"
763
764	## /second/equal/first:
765	file /second/equal/first/file "bar"
766	fifo /second/equal/first/fifo
767	link /second/equal/first/link "new"
768	missing /second/equal/first/emptydir
769	file /second/equal/first/fulldir/file "foo"
770
771	## /second/second/equal:
772	fifo /second/second/equal/fifo
773	file /second/second/equal/file "foo"
774	dir /second/second/equal/dir
775	link /second/second/equal/link "bar"
776
777	## /second/second/difftype:
778	fifo /second/second/difftype/dir
779
780	## /second/second/difflinks:
781	link /second/second/difflinks/link "test link"
782
783	## /second/second/difffiles:
784	file /second/second/difffiles/file "test"
785	conflict /second/second/difffiles/file 4f2ee8620a251fd53f06bb6112eb6ffa
786
787	## /difftype/equal/difftype:
788	link /difftype/equal/difftype/file "test"
789	fifo /difftype/equal/difftype/fromdir
790	missing /difftype/equal/difftype/todir
791
792	## /difftype/first/first:
793	missing /difftype/first/first/fifo
794
795	## /difftype/difftype/equal:
796	fifo /difftype/difftype/equal/fifo
797	file /difftype/difftype/equal/file "bar"
798
799	## /difftype/difftype/difftype:
800	file /difftype/difftype/difftype/one "foo"
801	link /difftype/difftype/difftype/two "bar"
802
803	## /difftype/difftype/difflinks:
804	link /difftype/difftype/difflinks/link "test"
805
806	## /difftype/difftype/difffile:
807	conflict /difftype/difftype/difffiles/file \
808	    117f2bcd1f6491f6044e79e5a57a9229
809
810	## /difflinks/equal/difflinks:
811	link /difflinks/equal/difflinks/link "new"
812
813	## /difflinks/first/first:
814	missing /difflinks/first/first/link
815
816	## /difflinks/difftype/difftype:
817	file /difflinks/difftype/difftype/link "test"
818
819	## /difflinks/difflinks/equal:
820	link /difflinks/difflinks/equal/link "new"
821
822	## /difflinks/difflinks/difflinks:
823	link /difflinks/difflinks/difflinks/link "test"
824
825	## /difffiles/equal/difffiles:
826	file /difffiles/equal/difffiles/file "bar"
827
828	## /difffiles/first/first:
829	missing /difffiles/first/first/file
830
831	## /difffiles/difftype/difftype:
832	fifo /difffiles/difftype/difftype/file
833
834	## /difffiles/difffiles/equal:
835	file /difffiles/difffiles/equal/file "bar"
836
837	## /difffiles/difffiles/difffiles:
838	file /difffiles/difffiles/difffiles/simple "" \
839	    cabc7e5e80b0946d79edd555e9648486
840	file /difffiles/difffiles/difffiles/conflict "this is a test file"
841	conflict /difffiles/difffiles/difffiles/conflict \
842	    8261cfdd89280c4a6c26e4ac86541fe9
843
844	## /adddir/conflict:
845	file /adddir/conflict
846
847	## /adddir/partial:
848	file /adddir/partial/file "foo"
849	fifo /adddir/partial/fifo
850
851	## /rmdir/extra:
852	dir /rmdir/extra
853	file /rmdir/extra/localfile.txt "foo"
854
855	## /rmdir/conflict:
856	dir /rmdir/conflict/difftype
857	present /rmdir/conflict
858
859	## /rmdir/partial:
860	missing /rmdir/partial
861
862	## /dirchange/already/fromdir:
863	file /dirchange/already/fromdir "bar"
864
865	## /dirchange/already/todir:
866	file /dirchange/already/todir/somefile "blah"
867
868	## /dirchange/old/fromdir:
869	file /dirchange/old/fromdir "bar"
870
871	## /dirchange/old/todir
872	file /dirchange/old/todir/file "bar"
873
874	## /dirchange/fromdir/extradir:
875	missing /dirchange/fromdir/extradir/file
876	fifo /dirchange/fromdir/extradir/fifo
877
878	## /dirchange/fromdir/conflict:
879	file /dirchange/fromdir/conflict/somefile "bar"
880
881	## /dirchange/todir/difffile:
882	file /dirchange/todir/difffile "bar"
883
884	## /dirchange/todir/difftype:
885	fifo /dirchange/todir/difftype
886
887	## Tests for post-install actions
888	file /etc/master.passwd
889	file /etc/passwd
890	file /etc/pwd.db
891	file /etc/spwd.db
892	file /etc/login.conf "" 7774a0f9a3a372c7c109c32fd31c4b6b
893	file /etc/login.conf.db
894	file /etc/mail/aliases "" 7d598f89ec040ab56af54011bdb83337
895}
896
897if [ `id -u` -ne 0 ]; then
898	echo "must be root"
899fi
900
901if [ -r /etc/etcupdate.conf ]; then
902	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
903fi
904
905build_trees
906
907etcupdate -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
908
909cat > $WORKDIR/correct.out <<EOF
910  D /dirchange/fromdir/extradir/file
911  D /dirchange/old/fromdir/somefile
912  D /first/equal/second/fifo
913  D /first/equal/second/file
914  D /first/equal/second/fulldir/file
915  D /first/equal/second/link
916  D /rmdir/partial/subdir/fifo
917  D /rmdir/partial/subdir
918  D /rmdir/partial
919  D /first/equal/second/fulldir
920  D /first/equal/second/emptydir
921  C /difffiles/difffiles/difffiles/conflict
922  M /difffiles/difffiles/difffiles/simple
923  U /difffiles/equal/difffiles/file
924  U /difflinks/equal/difflinks/link
925  C /difftype/difftype/difffiles/file
926  U /difftype/equal/difftype/file
927  U /difftype/equal/difftype/fromdir
928  D /difftype/equal/difftype/todir
929  U /dirchange/old/fromdir
930  U /dirchange/old/todir
931  U /etc/login.conf
932  M /etc/mail/aliases
933  A /adddir/partial/file
934  A /dirchange/old/todir/file
935  A /etc/master.passwd
936  A /second/equal/first/fifo
937  A /second/equal/first/file
938  A /second/equal/first/fulldir/file
939  A /second/equal/first/link
940  C /second/second/difffiles/file
941Warnings:
942  Modified regular file remains: /dirchange/fromdir/conflict/somefile
943  Modified regular file remains: /first/difffiles/second/file
944  Modified symbolic link remains: /first/difflinks/second/link
945  Modified directory remains: /first/difftype/second/fifo
946  Modified directory remains: /rmdir/conflict/difftype
947  Non-empty directory remains: /rmdir/extra
948  Non-empty directory remains: /rmdir/conflict
949  Modified mismatch: /difffiles/difftype/difftype/file (regular file vs fifo file)
950  Removed file changed: /difffiles/first/first/file
951  Modified link changed: /difflinks/difflinks/difflinks/link ("old" became "new")
952  Modified mismatch: /difflinks/difftype/difftype/link (symbolic link vs regular file)
953  Removed link changed: /difflinks/first/first/link ("old" became "new")
954  New link conflict: /difftype/difftype/difflinks/link ("new" vs "test")
955  Modified regular file changed: /difftype/difftype/difftype/one (fifo file became directory)
956  Modified symbolic link changed: /difftype/difftype/difftype/two (directory became regular file)
957  Remove mismatch: /difftype/first/first/fifo (fifo file became directory)
958  Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file)
959  Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link)
960  Modified regular file changed: /dirchange/todir/difffile (regular file became directory)
961  Modified fifo file changed: /dirchange/todir/difftype (regular file became directory)
962  New file mismatch: /adddir/conflict (directory vs regular file)
963  Directory mismatch: $TEST/adddir/conflict (regular file)
964  Directory mismatch: $TEST/dirchange/todir/difffile (regular file)
965  Directory mismatch: $TEST/dirchange/todir/difftype (fifo file)
966  New link conflict: /second/second/difflinks/link ("new link" vs "test link")
967  New file mismatch: /second/second/difftype/dir (directory vs fifo file)
968  Needs update: /etc/mail/aliases.db (requires manual update via newaliases(1))
969EOF
970
971echo "Differences for -n:"
972diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
973
974etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
975
976echo "Differences for real:"
977diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
978
979check_trees
980