xref: /freebsd/usr.sbin/etcupdate/tests/fbsdid_test.sh (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
1#!/bin/sh
2#
3# Copyright (c) 2010 Hudson River Trading 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 test the -F flag to the 'update' command.
31
32FAILED=no
33WORKDIR=work
34
35usage()
36{
37	echo "Usage: fbsdid.sh [-s script] [-w workdir]"
38	exit 1
39}
40
41# Allow the user to specify an alternate work directory or script.
42COMMAND=etcupdate
43while getopts "s:w:" option; do
44	case $option in
45		s)
46			COMMAND="sh $OPTARG"
47			;;
48		w)
49			WORKDIR=$OPTARG
50			;;
51		*)
52			echo
53			usage
54			;;
55	esac
56done
57shift $((OPTIND - 1))
58if [ $# -ne 0 ]; then
59	usage
60fi
61
62CONFLICTS=$WORKDIR/conflicts
63OLD=$WORKDIR/old
64NEW=$WORKDIR/current
65TEST=$WORKDIR/test
66
67# Store a FreeBSD ID string in a specified file.  The first argument
68# is the file, the remaining arguments are the comment to use.
69store_id()
70{
71	local file
72
73	file=$1
74	shift
75
76	echo -n '# $FreeBSD' >> $file
77	echo -n "$@" >> $file
78	echo '$' >> $file
79}
80
81# These tests deal with FreeBSD ID string conflicts.  We run the test
82# twice, once without -F and once with -F.
83build_trees()
84{
85	local i
86
87	rm -rf $OLD $NEW $TEST $CONFLICTS
88	mkdir -p $OLD $NEW $TEST
89
90	# remove: Remove a file where the only local difference is a
91	# change in the FreeBSD ID string.
92	store_id $OLD/remove
93	store_id $TEST/remove ": head/remove 12345 jhb "
94
95	# old: Modify a file where the only local difference between
96	# the old and test files is a change in the FreeBSD ID string.
97	store_id $OLD/old ": src/old,v 1.1 jhb Exp "
98	store_id $NEW/old ": head/old 12345 jhb "
99	store_id $TEST/old ": head/old 12000 jhb "
100	for i in $OLD $TEST; do
101		cat >> $i/old <<EOF
102
103an old file
104EOF
105	done
106	cat >> $NEW/old <<EOF
107
108a new file
109EOF
110
111	# already: Modify a file where the local file already matches
112	# the new file except for a change in the FreeBSD ID string.
113	store_id $OLD/already ": src/already,v 1.1 jhb Exp "
114	store_id $NEW/already ": head/already 12345 jhb "
115	store_id $TEST/already ": src/already,v 1.2 jhb Exp "
116	cat >> $OLD/already <<EOF
117
118another old file
119EOF
120	for i in $NEW $TEST; do
121		cat >> $i/already <<EOF
122
123another new file
124EOF
125	done
126
127	# add: Add a file that already exists where the only local
128	# difference is a change in the FreeBSD ID string.
129	store_id $NEW/add ": head/add 12345 jhb "
130	store_id $TEST/add ""
131
132	# conflict: Modify a file where the local file has a different
133	# FreeBSD ID string.  This should still generate a conflict
134	# even in the -F case.
135	store_id $OLD/conflict ": head/conflict 12000 jhb "
136	store_id $NEW/conflict ": head/conflict 12345 jhb "
137	store_id $TEST/conflict ""
138	cat >> $OLD/conflict <<EOF
139
140this is the old file
141EOF
142	cat >> $NEW/conflict <<EOF
143
144this is the new file
145EOF
146	cat >> $TEST/conflict <<EOF
147
148this is the local file
149EOF
150
151	# local: A file with local modifications has a different
152	# FreeBSD ID string and the only differences between the old
153	# and new versions are a change in the FreeBSD ID string.
154	# This will just update the FreeBSD ID string in the -F case.
155	for i in $OLD $NEW $TEST; do
156		cat >> $i/local <<EOF
157# Some leading text
158#
159EOF
160	done
161
162	store_id $OLD/local ": head/local 12000 jhb "
163	store_id $NEW/local ": head/local 12345 jhb "
164	store_id $TEST/local ": src/local,v 1.5 jhb Exp "
165
166	for i in $OLD $NEW $TEST; do
167		cat >> $i/local <<EOF
168
169this is a file
170EOF
171	done
172
173	cat >> $TEST/local <<EOF
174
175these are some local mods to the file
176EOF
177
178	# local-already: A file with local modifications has the same
179	# FreeBSD ID string as the new version of the file and the
180	# only differences between the old and new versions are a
181	# change in the FreeBSD ID string.  Nothing should happen in
182	# the -F case.
183	store_id $OLD/local-already ": head/local 12000 jhb "
184	for i in $NEW $TEST; do
185		store_id $i/local-already ": head/local 12345 jhb "
186	done
187
188	for i in $OLD $NEW $TEST; do
189		cat >> $i/local-already <<EOF
190
191this is a file
192EOF
193	done
194
195	cat >> $TEST/local-already <<EOF
196
197these are some local mods to the file
198EOF
199
200	# local-remove: A file removed locally changed it's FreeBSD ID
201	# but nothing else
202	store_id $OLD/local-remove ": head/local-remove 12000 jhb "
203	store_id $NEW/local-remove ": head/local-remove 12345 jhb "
204	for i in $OLD $NEW; do
205		cat >> $i/local-remove <<EOF
206
207this is a file
208EOF
209	done
210}
211
212# $1 - relative path to file that should be missing from TEST
213missing()
214{
215	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
216		echo "File $1 should be missing"
217		FAILED=yes
218	fi
219}
220
221# $1 - relative path to file that should be present in TEST
222present()
223{
224	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
225		echo "File $1 should be present"
226		FAILED=yes
227	fi
228}
229
230# $1 - relative path to regular file that should be present in TEST
231# $2 - optional string that should match file contents
232# $3 - optional MD5 of the flie contents, overrides $2 if present
233file()
234{
235	local contents sum
236
237	if ! [ -f $TEST/$1 ]; then
238		echo "File $1 should be a regular file"
239		FAILED=yes
240	elif [ $# -eq 2 ]; then
241		contents=`cat $TEST/$1`
242		if [ "$contents" != "$2" ]; then
243			echo "File $1 has wrong contents"
244			FAILED=yes
245		fi
246	elif [ $# -eq 3 ]; then
247		sum=`md5 -q $TEST/$1`
248		if [ "$sum" != "$3" ]; then
249			echo "File $1 has wrong contents"
250			FAILED=yes
251		fi
252	fi
253}
254
255# $1 - relative path to a regular file that should have a conflict
256# $2 - optional MD5 of the conflict file contents
257conflict()
258{
259	local sum
260
261	if ! [ -f $CONFLICTS/$1 ]; then
262		echo "File $1 missing conflict"
263		FAILED=yes
264	elif [ $# -gt 1 ]; then
265		sum=`md5 -q $CONFLICTS/$1`
266		if [ "$sum" != "$2" ]; then
267			echo "Conflict $1 has wrong contents"
268			FAILED=yes
269		fi
270	fi
271}
272
273# $1 - relative path to a regular file that should not have a conflict
274noconflict()
275{
276	if [ -f $CONFLICTS/$1 ]; then
277		echo "File $1 should not have a conflict"
278		FAILED=yes
279	fi
280}
281
282if [ `id -u` -ne 0 ]; then
283	echo "must be root"
284	exit 0
285fi
286
287if [ -r /etc/etcupdate.conf ]; then
288	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
289fi
290
291# First run the test without -F.
292
293build_trees
294
295$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
296
297cat > $WORKDIR/correct.out <<EOF
298  C /already
299  C /conflict
300  C /local
301  M /local-already
302  C /old
303  C /add
304Warnings:
305  Modified regular file remains: /remove
306  Removed file changed: /local-remove
307EOF
308
309echo "Differences for regular:"
310diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
311    || FAILED=yes
312
313file /remove "" 1bb4776213af107077be78fead8a351c
314file /old "" 2f799a7addc4132563ef9b44adc66157
315conflict /old 8441be64a1540f2ff584015279682425
316file /already "" aa53bd506f65d01d766e7ba028585e1d
317conflict /already f44105abb1fa3293e95c5d77e428d418
318file /add "" 1dc8c617e541d1fd1b4c70212f71d8ae
319conflict /add f99081e0da9a07f3cfebb430c0414941
320file /conflict "" dc27978df125b0daeb7d9b93265f03fd
321conflict /conflict 868452f666fea1c60ffb918ad9ad9607
322file /local "" aa33e614b5e749449f230e2a2b0072eb
323conflict /local 3df93e64043c8e348fc625b93ea220f4
324file /local-already "" 0298b958a603049f45ae6a109c4f7fea
325missing /local-remove
326
327# Now test with -F.
328
329build_trees
330
331$COMMAND -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
332
333cat > $WORKDIR/correctF.out <<EOF
334  D /remove
335  U /already
336  C /conflict
337  M /local
338  U /old
339  U /add
340EOF
341
342echo "Differences for -F:"
343diff -u -L "correct" $WORKDIR/correctF.out -L "test" $WORKDIR/testF.out \
344    || FAILED=yes
345
346missing /remove
347file /old "" 6a9f34f109d94406a4de3bc5d72de259
348noconflict /old
349file /already "" 21f4eca3aacc702c49878c8da7afd3d0
350noconflict /already
351file /add "" 0208bd647111fedf6318511712ab9e97
352noconflict /add
353file /conflict "" dc27978df125b0daeb7d9b93265f03fd
354conflict /conflict 868452f666fea1c60ffb918ad9ad9607
355file /local "" 3ed5a35e380c8a93fb5f599d4c052713
356file /local-already "" 0298b958a603049f45ae6a109c4f7fea
357missing /local-remove
358
359# Now test with -F and -A forcing all installs.  (-A should have
360# precedence over -F)
361
362build_trees
363
364$COMMAND -A '/*' -rF -d $WORKDIR -D $TEST > $WORKDIR/testAF.out
365
366cat > $WORKDIR/correctAF.out <<EOF
367  D /remove
368  U /already
369  U /conflict
370  U /local
371  U /local-already
372  A /local-remove
373  U /old
374  U /add
375EOF
376
377echo "Differences for -A '/*' -F:"
378diff -u -L "correct" $WORKDIR/correctAF.out -L "test" $WORKDIR/testAF.out \
379    || FAILED=yes
380
381missing /remove
382file /old "" 6a9f34f109d94406a4de3bc5d72de259
383noconflict /old
384file /already "" 21f4eca3aacc702c49878c8da7afd3d0
385noconflict /already
386file /add "" 0208bd647111fedf6318511712ab9e97
387noconflict /add
388file /conflict "" 75ee141c4136beaf14e39de92efa84e4
389noconflict /conflict
390file /local "" 6a8fc5c2755b7a49015089f5e1dbe092
391file /local-already "" 49045f8b51542dd634655301cd296f66
392file /local-remove "" 5c38322efed4014797d7127f5c652d9d
393
394[ "${FAILED}" = no ]
395