1238423Sjhb#!/bin/sh
2238423Sjhb#
3283927Sjhb# Copyright (c) 2010 Hudson River Trading LLC
4238423Sjhb# Written by: John H. Baldwin <jhb@FreeBSD.org>
5238423Sjhb# All rights reserved.
6238423Sjhb#
7238423Sjhb# Redistribution and use in source and binary forms, with or without
8238423Sjhb# modification, are permitted provided that the following conditions
9238423Sjhb# are met:
10238423Sjhb# 1. Redistributions of source code must retain the above copyright
11238423Sjhb#    notice, this list of conditions and the following disclaimer.
12238423Sjhb# 2. Redistributions in binary form must reproduce the above copyright
13238423Sjhb#    notice, this list of conditions and the following disclaimer in the
14238423Sjhb#    documentation and/or other materials provided with the distribution.
15238423Sjhb#
16238423Sjhb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17238423Sjhb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18238423Sjhb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19238423Sjhb# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20238423Sjhb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21238423Sjhb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22238423Sjhb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23238423Sjhb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24238423Sjhb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25238423Sjhb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26238423Sjhb# SUCH DAMAGE.
27238423Sjhb#
28238423Sjhb# $FreeBSD$
29238423Sjhb
30238423Sjhb# Various regression tests to test the -F flag to the 'update' command.
31238423Sjhb
32263221SjmmvFAILED=no
33238423SjhbWORKDIR=work
34238423Sjhb
35238423Sjhbusage()
36238423Sjhb{
37258063Sjhb	echo "Usage: fbsdid.sh [-s script] [-w workdir]"
38238423Sjhb	exit 1
39238423Sjhb}
40238423Sjhb
41258063Sjhb# Allow the user to specify an alternate work directory or script.
42258063SjhbCOMMAND=etcupdate
43258063Sjhbwhile getopts "s:w:" option; do
44238423Sjhb	case $option in
45258063Sjhb		s)
46258063Sjhb			COMMAND="sh $OPTARG"
47258063Sjhb			;;
48238423Sjhb		w)
49238423Sjhb			WORKDIR=$OPTARG
50238423Sjhb			;;
51238423Sjhb		*)
52238423Sjhb			echo
53238423Sjhb			usage
54238423Sjhb			;;
55238423Sjhb	esac
56238423Sjhbdone
57238423Sjhbshift $((OPTIND - 1))
58238423Sjhbif [ $# -ne 0 ]; then
59238423Sjhb	usage
60238423Sjhbfi
61238423Sjhb
62238423SjhbCONFLICTS=$WORKDIR/conflicts
63238423SjhbOLD=$WORKDIR/old
64238423SjhbNEW=$WORKDIR/current
65238423SjhbTEST=$WORKDIR/test
66238423Sjhb
67238423Sjhb# Store a FreeBSD ID string in a specified file.  The first argument
68238423Sjhb# is the file, the remaining arguments are the comment to use.
69238423Sjhbstore_id()
70238423Sjhb{
71238423Sjhb	local file
72238423Sjhb
73238423Sjhb	file=$1
74238423Sjhb	shift
75238423Sjhb
76238423Sjhb	echo -n '# $FreeBSD' >> $file
77238423Sjhb	echo -n "$@" >> $file
78238423Sjhb	echo '$' >> $file
79238423Sjhb}
80238423Sjhb
81238423Sjhb# These tests deal with FreeBSD ID string conflicts.  We run the test
82238423Sjhb# twice, once without -F and once with -F.
83238423Sjhbbuild_trees()
84238423Sjhb{
85238423Sjhb	local i
86238423Sjhb
87238423Sjhb	rm -rf $OLD $NEW $TEST $CONFLICTS
88238423Sjhb	mkdir -p $OLD $NEW $TEST
89238423Sjhb
90238423Sjhb	# remove: Remove a file where the only local difference is a
91238423Sjhb	# change in the FreeBSD ID string.
92238423Sjhb	store_id $OLD/remove
93238423Sjhb	store_id $TEST/remove ": head/remove 12345 jhb "
94238423Sjhb
95238423Sjhb	# old: Modify a file where the only local difference between
96238423Sjhb	# the old and test files is a change in the FreeBSD ID string.
97238423Sjhb	store_id $OLD/old ": src/old,v 1.1 jhb Exp "
98238423Sjhb	store_id $NEW/old ": head/old 12345 jhb "
99238423Sjhb	store_id $TEST/old ": head/old 12000 jhb "
100238423Sjhb	for i in $OLD $TEST; do
101238423Sjhb		cat >> $i/old <<EOF
102238423Sjhb
103238423Sjhban old file
104238423SjhbEOF
105238423Sjhb	done
106238423Sjhb	cat >> $NEW/old <<EOF
107238423Sjhb
108238423Sjhba new file
109238423SjhbEOF
110238423Sjhb
111238423Sjhb	# already: Modify a file where the local file already matches
112238423Sjhb	# the new file except for a change in the FreeBSD ID string.
113238423Sjhb	store_id $OLD/already ": src/already,v 1.1 jhb Exp "
114238423Sjhb	store_id $NEW/already ": head/already 12345 jhb "
115238423Sjhb	store_id $TEST/already ": src/already,v 1.2 jhb Exp "
116238423Sjhb	cat >> $OLD/already <<EOF
117238423Sjhb
118238423Sjhbanother old file
119238423SjhbEOF
120238423Sjhb	for i in $NEW $TEST; do
121238423Sjhb		cat >> $i/already <<EOF
122238423Sjhb
123238423Sjhbanother new file
124238423SjhbEOF
125238423Sjhb	done
126238423Sjhb
127238423Sjhb	# add: Add a file that already exists where the only local
128238423Sjhb	# difference is a change in the FreeBSD ID string.
129238423Sjhb	store_id $NEW/add ": head/add 12345 jhb "
130238423Sjhb	store_id $TEST/add ""
131238423Sjhb
132238423Sjhb	# conflict: Modify a file where the local file has a different
133238423Sjhb	# FreeBSD ID string.  This should still generate a conflict
134238423Sjhb	# even in the -F case.
135238423Sjhb	store_id $OLD/conflict ": head/conflict 12000 jhb "
136238423Sjhb	store_id $NEW/conflict ": head/conflict 12345 jhb "
137238423Sjhb	store_id $TEST/conflict ""
138238423Sjhb	cat >> $OLD/conflict <<EOF
139238423Sjhb
140238423Sjhbthis is the old file
141238423SjhbEOF
142238423Sjhb	cat >> $NEW/conflict <<EOF
143238423Sjhb
144238423Sjhbthis is the new file
145238423SjhbEOF
146238423Sjhb	cat >> $TEST/conflict <<EOF
147238423Sjhb
148238423Sjhbthis is the local file
149238423SjhbEOF
150238423Sjhb
151238423Sjhb	# local: A file with local modifications has a different
152238423Sjhb	# FreeBSD ID string and the only differences between the old
153238423Sjhb	# and new versions are a change in the FreeBSD ID string.
154238423Sjhb	# This will just update the FreeBSD ID string in the -F case.
155238423Sjhb	for i in $OLD $NEW $TEST; do
156238423Sjhb		cat >> $i/local <<EOF
157238423Sjhb# Some leading text
158238423Sjhb#
159238423SjhbEOF
160238423Sjhb	done
161238423Sjhb
162238423Sjhb	store_id $OLD/local ": head/local 12000 jhb "
163238423Sjhb	store_id $NEW/local ": head/local 12345 jhb "
164238423Sjhb	store_id $TEST/local ": src/local,v 1.5 jhb Exp "
165238423Sjhb
166238423Sjhb	for i in $OLD $NEW $TEST; do
167238423Sjhb		cat >> $i/local <<EOF
168238423Sjhb
169238423Sjhbthis is a file
170238423SjhbEOF
171238423Sjhb	done
172238423Sjhb
173238423Sjhb	cat >> $TEST/local <<EOF
174238423Sjhb
175238423Sjhbthese are some local mods to the file
176238423SjhbEOF
177238423Sjhb
178238423Sjhb	# local-already: A file with local modifications has the same
179238423Sjhb	# FreeBSD ID string as the new version of the file and the
180238423Sjhb	# only differences between the old and new versions are a
181238423Sjhb	# change in the FreeBSD ID string.  Nothing should happen in
182238423Sjhb	# the -F case.
183238423Sjhb	store_id $OLD/local-already ": head/local 12000 jhb "
184238423Sjhb	for i in $NEW $TEST; do
185238423Sjhb		store_id $i/local-already ": head/local 12345 jhb "
186238423Sjhb	done
187238423Sjhb
188238423Sjhb	for i in $OLD $NEW $TEST; do
189238423Sjhb		cat >> $i/local-already <<EOF
190238423Sjhb
191238423Sjhbthis is a file
192238423SjhbEOF
193238423Sjhb	done
194238423Sjhb
195238423Sjhb	cat >> $TEST/local-already <<EOF
196238423Sjhb
197238423Sjhbthese are some local mods to the file
198238423SjhbEOF
199258185Sjhb
200258185Sjhb	# local-remove: A file removed locally changed it's FreeBSD ID
201258185Sjhb	# but nothing else
202258185Sjhb	store_id $OLD/local-remove ": head/local-remove 12000 jhb "
203258185Sjhb	store_id $NEW/local-remove ": head/local-remove 12345 jhb "
204258185Sjhb	for i in $OLD $NEW; do
205258185Sjhb		cat >> $i/local-remove <<EOF
206258185Sjhb
207258185Sjhbthis is a file
208258185SjhbEOF
209258185Sjhb	done
210238423Sjhb}
211238423Sjhb
212238423Sjhb# $1 - relative path to file that should be missing from TEST
213238423Sjhbmissing()
214238423Sjhb{
215238423Sjhb	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
216238423Sjhb		echo "File $1 should be missing"
217263221Sjmmv		FAILED=yes
218238423Sjhb	fi
219238423Sjhb}
220238423Sjhb
221238423Sjhb# $1 - relative path to file that should be present in TEST
222238423Sjhbpresent()
223238423Sjhb{
224238423Sjhb	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
225238423Sjhb		echo "File $1 should be present"
226263221Sjmmv		FAILED=yes
227238423Sjhb	fi
228238423Sjhb}
229238423Sjhb
230238423Sjhb# $1 - relative path to regular file that should be present in TEST
231238423Sjhb# $2 - optional string that should match file contents
232238423Sjhb# $3 - optional MD5 of the flie contents, overrides $2 if present
233238423Sjhbfile()
234238423Sjhb{
235238423Sjhb	local contents sum
236238423Sjhb
237238423Sjhb	if ! [ -f $TEST/$1 ]; then
238238423Sjhb		echo "File $1 should be a regular file"
239263221Sjmmv		FAILED=yes
240238423Sjhb	elif [ $# -eq 2 ]; then
241238423Sjhb		contents=`cat $TEST/$1`
242238423Sjhb		if [ "$contents" != "$2" ]; then
243238423Sjhb			echo "File $1 has wrong contents"
244263221Sjmmv			FAILED=yes
245238423Sjhb		fi
246238423Sjhb	elif [ $# -eq 3 ]; then
247238423Sjhb		sum=`md5 -q $TEST/$1`
248238423Sjhb		if [ "$sum" != "$3" ]; then
249238423Sjhb			echo "File $1 has wrong contents"
250263221Sjmmv			FAILED=yes
251238423Sjhb		fi
252238423Sjhb	fi
253238423Sjhb}
254238423Sjhb
255238423Sjhb# $1 - relative path to a regular file that should have a conflict
256238423Sjhb# $2 - optional MD5 of the conflict file contents
257238423Sjhbconflict()
258238423Sjhb{
259238423Sjhb	local sum
260238423Sjhb
261238423Sjhb	if ! [ -f $CONFLICTS/$1 ]; then
262238423Sjhb		echo "File $1 missing conflict"
263263221Sjmmv		FAILED=yes
264238423Sjhb	elif [ $# -gt 1 ]; then
265238423Sjhb		sum=`md5 -q $CONFLICTS/$1`
266238423Sjhb		if [ "$sum" != "$2" ]; then
267238423Sjhb			echo "Conflict $1 has wrong contents"
268263221Sjmmv			FAILED=yes
269238423Sjhb		fi
270238423Sjhb	fi
271238423Sjhb}
272238423Sjhb
273238423Sjhb# $1 - relative path to a regular file that should not have a conflict
274238423Sjhbnoconflict()
275238423Sjhb{
276238423Sjhb	if [ -f $CONFLICTS/$1 ]; then
277238423Sjhb		echo "File $1 should not have a conflict"
278263221Sjmmv		FAILED=yes
279238423Sjhb	fi
280238423Sjhb}
281238423Sjhb
282238423Sjhbif [ `id -u` -ne 0 ]; then
283238423Sjhb	echo "must be root"
284263221Sjmmv	exit 0
285238423Sjhbfi
286238423Sjhb
287238423Sjhbif [ -r /etc/etcupdate.conf ]; then
288238423Sjhb	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
289238423Sjhbfi
290238423Sjhb
291238423Sjhb# First run the test without -F.
292238423Sjhb
293238423Sjhbbuild_trees
294238423Sjhb
295258063Sjhb$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
296238423Sjhb
297238423Sjhbcat > $WORKDIR/correct.out <<EOF
298238423Sjhb  C /already
299238423Sjhb  C /conflict
300238423Sjhb  C /local
301238423Sjhb  M /local-already
302238423Sjhb  C /old
303238423Sjhb  C /add
304238423SjhbWarnings:
305238423Sjhb  Modified regular file remains: /remove
306258185Sjhb  Removed file changed: /local-remove
307238423SjhbEOF
308238423Sjhb
309238423Sjhbecho "Differences for regular:"
310263221Sjmmvdiff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
311263221Sjmmv    || FAILED=yes
312238423Sjhb
313238423Sjhbfile /remove "" 1bb4776213af107077be78fead8a351c
314238423Sjhbfile /old "" 2f799a7addc4132563ef9b44adc66157
315238423Sjhbconflict /old 8441be64a1540f2ff584015279682425
316238423Sjhbfile /already "" aa53bd506f65d01d766e7ba028585e1d
317238423Sjhbconflict /already f44105abb1fa3293e95c5d77e428d418
318238423Sjhbfile /add "" 1dc8c617e541d1fd1b4c70212f71d8ae
319238423Sjhbconflict /add f99081e0da9a07f3cfebb430c0414941
320238423Sjhbfile /conflict "" dc27978df125b0daeb7d9b93265f03fd
321238423Sjhbconflict /conflict 868452f666fea1c60ffb918ad9ad9607
322238423Sjhbfile /local "" aa33e614b5e749449f230e2a2b0072eb
323238423Sjhbconflict /local 3df93e64043c8e348fc625b93ea220f4
324238423Sjhbfile /local-already "" 0298b958a603049f45ae6a109c4f7fea
325258185Sjhbmissing /local-remove
326238423Sjhb
327238423Sjhb# Now test with -F.
328238423Sjhb
329238423Sjhbbuild_trees
330238423Sjhb
331258063Sjhb$COMMAND -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
332238423Sjhb
333238423Sjhbcat > $WORKDIR/correctF.out <<EOF
334238423Sjhb  D /remove
335238423Sjhb  U /already
336238423Sjhb  C /conflict
337238423Sjhb  M /local
338238423Sjhb  U /old
339238423Sjhb  U /add
340238423SjhbEOF
341238423Sjhb
342238423Sjhbecho "Differences for -F:"
343263221Sjmmvdiff -u -L "correct" $WORKDIR/correctF.out -L "test" $WORKDIR/testF.out \
344263221Sjmmv    || FAILED=yes
345238423Sjhb
346238423Sjhbmissing /remove
347238423Sjhbfile /old "" 6a9f34f109d94406a4de3bc5d72de259
348238423Sjhbnoconflict /old
349238423Sjhbfile /already "" 21f4eca3aacc702c49878c8da7afd3d0
350238423Sjhbnoconflict /already
351238423Sjhbfile /add "" 0208bd647111fedf6318511712ab9e97
352238423Sjhbnoconflict /add
353238423Sjhbfile /conflict "" dc27978df125b0daeb7d9b93265f03fd
354238423Sjhbconflict /conflict 868452f666fea1c60ffb918ad9ad9607
355238423Sjhbfile /local "" 3ed5a35e380c8a93fb5f599d4c052713
356238423Sjhbfile /local-already "" 0298b958a603049f45ae6a109c4f7fea
357258185Sjhbmissing /local-remove
358258185Sjhb
359258185Sjhb# Now test with -F and -A forcing all installs.  (-A should have
360258185Sjhb# precedence over -F)
361258185Sjhb
362258185Sjhbbuild_trees
363258185Sjhb
364258185Sjhb$COMMAND -A '/*' -rF -d $WORKDIR -D $TEST > $WORKDIR/testAF.out
365258185Sjhb
366258185Sjhbcat > $WORKDIR/correctAF.out <<EOF
367258185Sjhb  D /remove
368258185Sjhb  U /already
369258185Sjhb  U /conflict
370258185Sjhb  U /local
371258185Sjhb  U /local-already
372258185Sjhb  A /local-remove
373258185Sjhb  U /old
374258185Sjhb  U /add
375258185SjhbEOF
376258185Sjhb
377258185Sjhbecho "Differences for -A '/*' -F:"
378263221Sjmmvdiff -u -L "correct" $WORKDIR/correctAF.out -L "test" $WORKDIR/testAF.out \
379263221Sjmmv    || FAILED=yes
380258185Sjhb
381258185Sjhbmissing /remove
382258185Sjhbfile /old "" 6a9f34f109d94406a4de3bc5d72de259
383258185Sjhbnoconflict /old
384258185Sjhbfile /already "" 21f4eca3aacc702c49878c8da7afd3d0
385258185Sjhbnoconflict /already
386258185Sjhbfile /add "" 0208bd647111fedf6318511712ab9e97
387258185Sjhbnoconflict /add
388258185Sjhbfile /conflict "" 75ee141c4136beaf14e39de92efa84e4
389258185Sjhbnoconflict /conflict
390258185Sjhbfile /local "" 6a8fc5c2755b7a49015089f5e1dbe092
391258185Sjhbfile /local-already "" 49045f8b51542dd634655301cd296f66
392258185Sjhbfile /local-remove "" 5c38322efed4014797d7127f5c652d9d
393263221Sjmmv
394263221Sjmmv[ "${FAILED}" = no ]
395