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
29# Various regression tests to test the -I flag to the 'update' command.
30
31FAILED=no
32WORKDIR=work
33
34usage()
35{
36	echo "Usage: ignore.sh [-s script] [-w workdir]"
37	exit 1
38}
39
40# Allow the user to specify an alternate work directory or script.
41COMMAND=etcupdate
42while getopts "s:w:" option; do
43	case $option in
44		s)
45			COMMAND="sh $OPTARG"
46			;;
47		w)
48			WORKDIR=$OPTARG
49			;;
50		*)
51			echo
52			usage
53			;;
54	esac
55done
56shift $((OPTIND - 1))
57if [ $# -ne 0 ]; then
58	usage
59fi
60
61CONFLICTS=$WORKDIR/conflicts
62OLD=$WORKDIR/old
63NEW=$WORKDIR/current
64TEST=$WORKDIR/test
65
66# These tests deal with ignoring certain patterns of files.  We run the
67# test multiple times ignoring different patterns.
68build_trees()
69{
70	local i
71
72	rm -rf $OLD $NEW $TEST $CONFLICTS
73	mkdir -p $OLD $NEW $TEST
74
75	for i in $OLD $NEW $TEST; do
76		mkdir -p $i/tree
77	done
78
79	# tree: Test three different cases (add, modify, remove) that all
80	# match the tree/* glob.
81	echo "foo" > $NEW/tree/add
82	for i in $OLD $TEST; do
83		echo "old" > $i/tree/modify
84	done
85	echo "new" > $NEW/tree/modify
86	for i in $OLD $TEST; do
87		echo "old" > $i/tree/remove
88	done
89
90	# rmdir: Remove a whole tree.
91	for i in $OLD $TEST; do
92		mkdir $i/rmdir
93		echo "foo" > $i/rmdir/file
94	done
95}
96
97# $1 - relative path to file that should be missing from TEST
98missing()
99{
100	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
101		echo "File $1 should be missing"
102		FAILED=yes
103	fi
104}
105
106# $1 - relative path to file that should be present in TEST
107present()
108{
109	if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
110		echo "File $1 should be present"
111		FAILED=yes
112	fi
113}
114
115# $1 - relative path to file that should be a directory in TEST
116dir()
117{
118	if ! [ -d $TEST/$1 ]; then
119		echo "File $1 should be a directory"
120		FAILED=yes
121	fi
122}
123
124# $1 - relative path to regular file that should be present in TEST
125# $2 - optional string that should match file contents
126# $3 - optional MD5 of the flie contents, overrides $2 if present
127file()
128{
129	local contents sum
130
131	if ! [ -f $TEST/$1 ]; then
132		echo "File $1 should be a regular file"
133		FAILED=yes
134	elif [ $# -eq 2 ]; then
135		contents=`cat $TEST/$1`
136		if [ "$contents" != "$2" ]; then
137			echo "File $1 has wrong contents"
138			FAILED=yes
139		fi
140	elif [ $# -eq 3 ]; then
141		sum=`md5 -q $TEST/$1`
142		if [ "$sum" != "$3" ]; then
143			echo "File $1 has wrong contents"
144			FAILED=yes
145		fi
146	fi
147}
148
149# $1 - relative path to a regular file that should have a conflict
150# $2 - optional MD5 of the conflict file contents
151conflict()
152{
153	local sum
154
155	if ! [ -f $CONFLICTS/$1 ]; then
156		echo "File $1 missing conflict"
157		FAILED=yes
158	elif [ $# -gt 1 ]; then
159		sum=`md5 -q $CONFLICTS/$1`
160		if [ "$sum" != "$2" ]; then
161			echo "Conflict $1 has wrong contents"
162			FAILED=yes
163		fi
164	fi
165}
166
167# $1 - relative path to a regular file that should not have a conflict
168noconflict()
169{
170	if [ -f $CONFLICTS/$1 ]; then
171		echo "File $1 should not have a conflict"
172		FAILED=yes
173	fi
174}
175
176if [ `id -u` -ne 0 ]; then
177	echo "must be root"
178	exit 0
179fi
180
181if [ -r /etc/etcupdate.conf ]; then
182	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
183fi
184
185# First run the test ignoring no patterns.
186
187build_trees
188
189$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
190
191cat > $WORKDIR/correct.out <<EOF
192  D /rmdir/file
193  D /tree/remove
194  D /rmdir
195  U /tree/modify
196  A /tree/add
197EOF
198
199echo "Differences for regular:"
200diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
201    || FAILED=yes
202
203missing /tree/remove
204file /tree/modify "new"
205file /tree/add "foo"
206missing /rmdir/file
207missing /rmdir
208
209# Now test with -I '/tree/*'.  This should preserve the /tree files.
210
211build_trees
212
213$COMMAND -r -I '/tree/*' -d $WORKDIR -D $TEST > $WORKDIR/test1.out
214
215cat > $WORKDIR/correct1.out <<EOF
216  D /rmdir/file
217  D /rmdir
218EOF
219
220echo "Differences for -I '/tree/*':"
221diff -u -L "correct" $WORKDIR/correct1.out -L "test" $WORKDIR/test1.out \
222    || FAILED=yes
223
224file /tree/remove "old"
225file /tree/modify "old"
226missing /tree/add
227missing /rmdir/file
228missing /rmdir
229
230# Now test with two patterns.  This should preserve everything.
231
232build_trees
233
234$COMMAND -r -I '/tree/*' -I '/rmdir*' -d $WORKDIR -D $TEST > \
235    $WORKDIR/test2.out
236
237cat > $WORKDIR/correct2.out <<EOF
238EOF
239
240echo "Differences for -I '/tree/*' -I '/rmdir*':"
241
242diff -u -L "correct" $WORKDIR/correct2.out -L "test" $WORKDIR/test2.out \
243    || FAILED=yes
244
245file /tree/remove "old"
246file /tree/modify "old"
247missing /tree/add
248file /rmdir/file "foo"
249
250# Now test with a pattern that should cause a warning on /rmdir by
251# only ignoring the files under that directory.  Note that this also
252# tests putting two patterns into a single -I argument.
253
254build_trees
255
256$COMMAND -r -I '/tree/* /rmdir/*' -d $WORKDIR -D $TEST > \
257    $WORKDIR/test3.out
258
259cat > $WORKDIR/correct3.out <<EOF
260Warnings:
261  Non-empty directory remains: /rmdir
262EOF
263
264echo "Differences for -I '/tree/* /rmdir/*':"
265
266diff -u -L "correct" $WORKDIR/correct3.out -L "test" $WORKDIR/test3.out \
267    || FAILED=yes
268
269file /tree/remove "old"
270file /tree/modify "old"
271missing /tree/add
272file /rmdir/file "foo"
273dir /rmdir
274
275[ "${FAILED}" = no ]
276