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 test the -F flag to the 'update' command.
31
32WORKDIR=work
33
34usage()
35{
36	echo "Usage: fbsdid.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# Store a FreeBSD ID string in a specified file.  The first argument
63# is the file, the remaining arguments are the comment to use.
64store_id()
65{
66	local file
67
68	file=$1
69	shift
70
71	echo -n '# $FreeBSD' >> $file
72	echo -n "$@" >> $file
73	echo '$' >> $file
74}
75
76# These tests deal with FreeBSD ID string conflicts.  We run the test
77# twice, once without -F and once with -F.
78build_trees()
79{
80	local i
81
82	rm -rf $OLD $NEW $TEST $CONFLICTS
83	mkdir -p $OLD $NEW $TEST
84
85	# remove: Remove a file where the only local difference is a
86	# change in the FreeBSD ID string.
87	store_id $OLD/remove
88	store_id $TEST/remove ": head/remove 12345 jhb "
89
90	# old: Modify a file where the only local difference between
91	# the old and test files is a change in the FreeBSD ID string.
92	store_id $OLD/old ": src/old,v 1.1 jhb Exp "
93	store_id $NEW/old ": head/old 12345 jhb "
94	store_id $TEST/old ": head/old 12000 jhb "
95	for i in $OLD $TEST; do
96		cat >> $i/old <<EOF
97
98an old file
99EOF
100	done
101	cat >> $NEW/old <<EOF
102
103a new file
104EOF
105
106	# already: Modify a file where the local file already matches
107	# the new file except for a change in the FreeBSD ID string.
108	store_id $OLD/already ": src/already,v 1.1 jhb Exp "
109	store_id $NEW/already ": head/already 12345 jhb "
110	store_id $TEST/already ": src/already,v 1.2 jhb Exp "
111	cat >> $OLD/already <<EOF
112
113another old file
114EOF
115	for i in $NEW $TEST; do
116		cat >> $i/already <<EOF
117
118another new file
119EOF
120	done
121
122	# add: Add a file that already exists where the only local
123	# difference is a change in the FreeBSD ID string.
124	store_id $NEW/add ": head/add 12345 jhb "
125	store_id $TEST/add ""
126
127	# conflict: Modify a file where the local file has a different
128	# FreeBSD ID string.  This should still generate a conflict
129	# even in the -F case.
130	store_id $OLD/conflict ": head/conflict 12000 jhb "
131	store_id $NEW/conflict ": head/conflict 12345 jhb "
132	store_id $TEST/conflict ""
133	cat >> $OLD/conflict <<EOF
134
135this is the old file
136EOF
137	cat >> $NEW/conflict <<EOF
138
139this is the new file
140EOF
141	cat >> $TEST/conflict <<EOF
142
143this is the local file
144EOF
145
146	# local: A file with local modifications has a different
147	# FreeBSD ID string and the only differences between the old
148	# and new versions are a change in the FreeBSD ID string.
149	# This will just update the FreeBSD ID string in the -F case.
150	for i in $OLD $NEW $TEST; do
151		cat >> $i/local <<EOF
152# Some leading text
153#
154EOF
155	done
156
157	store_id $OLD/local ": head/local 12000 jhb "
158	store_id $NEW/local ": head/local 12345 jhb "
159	store_id $TEST/local ": src/local,v 1.5 jhb Exp "
160
161	for i in $OLD $NEW $TEST; do
162		cat >> $i/local <<EOF
163
164this is a file
165EOF
166	done
167
168	cat >> $TEST/local <<EOF
169
170these are some local mods to the file
171EOF
172
173	# local-already: A file with local modifications has the same
174	# FreeBSD ID string as the new version of the file and the
175	# only differences between the old and new versions are a
176	# change in the FreeBSD ID string.  Nothing should happen in
177	# the -F case.
178	store_id $OLD/local-already ": head/local 12000 jhb "
179	for i in $NEW $TEST; do
180		store_id $i/local-already ": head/local 12345 jhb "
181	done
182
183	for i in $OLD $NEW $TEST; do
184		cat >> $i/local-already <<EOF
185
186this is a file
187EOF
188	done
189
190	cat >> $TEST/local-already <<EOF
191
192these are some local mods to the file
193EOF
194}
195
196# $1 - relative path to file that should be missing from TEST
197missing()
198{
199	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
200		echo "File $1 should be missing"
201	fi
202}
203
204# $1 - relative path to file that should be present in TEST
205present()
206{
207	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
208		echo "File $1 should be present"
209	fi
210}
211
212# $1 - relative path to regular file that should be present in TEST
213# $2 - optional string that should match file contents
214# $3 - optional MD5 of the flie contents, overrides $2 if present
215file()
216{
217	local contents sum
218
219	if ! [ -f $TEST/$1 ]; then
220		echo "File $1 should be a regular file"
221	elif [ $# -eq 2 ]; then
222		contents=`cat $TEST/$1`
223		if [ "$contents" != "$2" ]; then
224			echo "File $1 has wrong contents"
225		fi
226	elif [ $# -eq 3 ]; then
227		sum=`md5 -q $TEST/$1`
228		if [ "$sum" != "$3" ]; then
229			echo "File $1 has wrong contents"
230		fi
231	fi
232}
233
234# $1 - relative path to a regular file that should have a conflict
235# $2 - optional MD5 of the conflict file contents
236conflict()
237{
238	local sum
239
240	if ! [ -f $CONFLICTS/$1 ]; then
241		echo "File $1 missing conflict"
242	elif [ $# -gt 1 ]; then
243		sum=`md5 -q $CONFLICTS/$1`
244		if [ "$sum" != "$2" ]; then
245			echo "Conflict $1 has wrong contents"
246		fi
247	fi
248}
249
250# $1 - relative path to a regular file that should not have a conflict
251noconflict()
252{
253	if [ -f $CONFLICTS/$1 ]; then
254		echo "File $1 should not have a conflict"
255	fi
256}
257
258if [ `id -u` -ne 0 ]; then
259	echo "must be root"
260fi
261
262if [ -r /etc/etcupdate.conf ]; then
263	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
264fi
265
266# First run the test without -F.
267
268build_trees
269
270etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
271
272cat > $WORKDIR/correct.out <<EOF
273  C /already
274  C /conflict
275  C /local
276  M /local-already
277  C /old
278  C /add
279Warnings:
280  Modified regular file remains: /remove
281EOF
282
283echo "Differences for regular:"
284diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
285
286file /remove "" 1bb4776213af107077be78fead8a351c
287file /old "" 2f799a7addc4132563ef9b44adc66157
288conflict /old 8441be64a1540f2ff584015279682425
289file /already "" aa53bd506f65d01d766e7ba028585e1d
290conflict /already f44105abb1fa3293e95c5d77e428d418
291file /add "" 1dc8c617e541d1fd1b4c70212f71d8ae
292conflict /add f99081e0da9a07f3cfebb430c0414941
293file /conflict "" dc27978df125b0daeb7d9b93265f03fd
294conflict /conflict 868452f666fea1c60ffb918ad9ad9607
295file /local "" aa33e614b5e749449f230e2a2b0072eb
296conflict /local 3df93e64043c8e348fc625b93ea220f4
297file /local-already "" 0298b958a603049f45ae6a109c4f7fea
298
299# Now test with -F.
300
301build_trees
302
303etcupdate -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
304
305cat > $WORKDIR/correctF.out <<EOF
306  D /remove
307  U /already
308  C /conflict
309  M /local
310  U /old
311  U /add
312EOF
313
314echo "Differences for -F:"
315diff -u -L "correct" $WORKDIR/correctF.out -L "test" $WORKDIR/testF.out
316
317missing /remove
318file /old "" 6a9f34f109d94406a4de3bc5d72de259
319noconflict /old
320file /already "" 21f4eca3aacc702c49878c8da7afd3d0
321noconflict /already
322file /add "" 0208bd647111fedf6318511712ab9e97
323noconflict /add
324file /conflict "" dc27978df125b0daeb7d9b93265f03fd
325conflict /conflict 868452f666fea1c60ffb918ad9ad9607
326file /local "" 3ed5a35e380c8a93fb5f599d4c052713
327file /local-already "" 0298b958a603049f45ae6a109c4f7fea
328