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