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 -A flag to the 'update' command. 31 32WORKDIR=work 33 34usage() 35{ 36 echo "Usage: always.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# The various states of the comparison of a file between two trees. 63states="equal first second difftype difflinks difffiles" 64 65# These tests deal with ignoring certain patterns of files. We run 66# the test multiple times forcing the install of different patterns. 67build_trees() 68{ 69 local i 70 71 rm -rf $OLD $NEW $TEST $CONFLICTS 72 73 for i in $states; do 74 for j in $states; do 75 for k in $states; do 76 mkdir -p $OLD/$i/$j/$k $NEW/$i/$j/$k \ 77 $TEST/$i/$j/$k 78 done 79 done 80 done 81 82 # What follows are the various warning/conflict cases from the 83 # larger regression tests. These results of many of these 84 # tests should be changed when installation is forced. The 85 # cases when these updates should still fail even when forced 86 # are: 1) it should not force the removal of a modified file 87 # and 2) it should not remove a subdirectory that contains a 88 # modified or added file. 89 90 # /first/difftype/second: File with different local type 91 # removed. Should generate a warning. 92 mkfifo $OLD/first/difftype/second/fifo 93 mkdir $TEST/first/difftype/second/fifo 94 95 # /first/difflinks/second: Modified link removed. Should 96 # generate a warning. 97 ln -s "old link" $OLD/first/difflinks/second/link 98 ln -s "test link" $TEST/first/difflinks/second/link 99 100 # /first/difffiles/second: Modified file removed. Should 101 # generate a warning. 102 echo "foo" > $OLD/first/difffiles/second/file 103 echo "bar" > $TEST/first/difffiles/second/file 104 105 # /second/second/difftype: Newly added file conflicts with 106 # existing file in test tree of a different type. Should 107 # generate a warning. 108 mkdir $NEW/second/second/difftype/dir 109 mkfifo $TEST/second/second/difftype/dir 110 111 # /second/second/difflinks: Newly added link conflicts with 112 # existing link in test tree. Should generate a warning. 113 ln -s "new link" $NEW/second/second/difflinks/link 114 ln -s "test link" $TEST/second/second/difflinks/link 115 116 # /second/second/difffiles: Newly added file conflicts with 117 # existing file in test tree. Should generate a warning. 118 echo "new" > $NEW/second/second/difffiles/file 119 echo "test" > $TEST/second/second/difffiles/file 120 121 # /difftype/first/first: A removed file has changed type. 122 # This should generate a warning. 123 mkfifo $OLD/difftype/first/first/fifo 124 mkdir $NEW/difftype/first/first/fifo 125 126 # /difftype/difftype/difftype: All three files (old, new, and 127 # test) are different types from each other. This should 128 # generate a warning. 129 mkfifo $OLD/difftype/difftype/difftype/one 130 mkdir $NEW/difftype/difftype/difftype/one 131 echo "foo" > $TEST/difftype/difftype/difftype/one 132 mkdir $OLD/difftype/difftype/difftype/two 133 echo "baz" > $NEW/difftype/difftype/difftype/two 134 ln -s "bar" $TEST/difftype/difftype/difftype/two 135 136 # /difftype/difftype/difflinks: A file has changed from a 137 # non-link to a link in both the new and test trees, but the 138 # target of the new and test links differ. This should 139 # generate a new link conflict. 140 mkfifo $OLD/difftype/difftype/difflinks/link 141 ln -s "new" $NEW/difftype/difftype/difflinks/link 142 ln -s "test" $TEST/difftype/difftype/difflinks/link 143 144 # /difftype/difftype/difffile: A file has changed from a 145 # non-regular file to a regular file in both the new and test 146 # trees, but the contents in the new and test files differ. 147 # This should generate a new file conflict. 148 ln -s "old" $OLD/difftype/difftype/difffiles/file 149 echo "foo" > $NEW/difftype/difftype/difffiles/file 150 echo "bar" > $TEST/difftype/difftype/difffiles/file 151 152 # /difflinks/first/first: A modified link is missing in the 153 # test tree. This should generate a warning. 154 ln -s "old" $OLD/difflinks/first/first/link 155 ln -s "new" $NEW/difflinks/first/first/link 156 157 # /difflinks/difftype/difftype: An updated link has been 158 # changed to a different file type in the test tree. This 159 # should generate a warning. 160 ln -s "old" $OLD/difflinks/difftype/difftype/link 161 ln -s "new" $NEW/difflinks/difftype/difftype/link 162 echo "test" > $TEST/difflinks/difftype/difftype/link 163 164 # /difflinks/difflinks/difflinks: An updated link has been 165 # modified in the test tree and doesn't match either the old 166 # or new links. This should generate a warning. 167 ln -s "old" $OLD/difflinks/difflinks/difflinks/link 168 ln -s "new" $NEW/difflinks/difflinks/difflinks/link 169 ln -s "test" $TEST/difflinks/difflinks/difflinks/link 170 171 # /difffiles/first/first: A removed file has been changed in 172 # the new tree. This should generate a warning. 173 echo "foo" > $OLD/difffiles/first/first/file 174 echo "bar" > $NEW/difffiles/first/first/file 175 176 # /difffiles/difftype/difftype: An updated regular file has 177 # been changed to a different file type in the test tree. 178 # This should generate a warning. 179 echo "old" > $OLD/difffiles/difftype/difftype/file 180 echo "new" > $NEW/difffiles/difftype/difftype/file 181 mkfifo $TEST/difffiles/difftype/difftype/file 182 183 # /difffiles/difffiles/difffiles: A modified regular file was 184 # updated in the new tree. The changes should be merged into 185 # to the new file if possible. If the merge fails, a conflict 186 # should be generated. For this test we just include the 187 # conflict case. 188 cat > $OLD/difffiles/difffiles/difffiles/conflict <<EOF 189this is an old file 190EOF 191 cat > $NEW/difffiles/difffiles/difffiles/conflict <<EOF 192this is a new file 193EOF 194 cat > $TEST/difffiles/difffiles/difffiles/conflict <<EOF 195this is a test file 196EOF 197 198 ## Tests for adding directories 199 mkdir -p $OLD/adddir $NEW/adddir $TEST/adddir 200 201 # /adddir/conflict: Add a new file in a directory that already 202 # exists as a file. This should generate two warnings. 203 mkdir $NEW/adddir/conflict 204 touch $NEW/adddir/conflict/newfile 205 touch $TEST/adddir/conflict 206 207 ## Tests for removing directories 208 mkdir -p $OLD/rmdir $NEW/rmdir $TEST/rmdir 209 210 # /rmdir/extra: Do not remove a directory with an extra local file. 211 # This should generate a warning. 212 for i in $OLD $TEST; do 213 mkdir $i/rmdir/extra 214 done 215 echo "foo" > $TEST/rmdir/extra/localfile.txt 216 217 # /rmdir/conflict: Do not remove a directory with a conflicted 218 # remove file. This should generate a warning. 219 for i in $OLD $TEST; do 220 mkdir $i/rmdir/conflict 221 done 222 mkfifo $OLD/rmdir/conflict/difftype 223 mkdir $TEST/rmdir/conflict/difftype 224 225 ## Tests for converting files to directories and vice versa 226 for i in $OLD $NEW $TEST; do 227 for j in already old fromdir todir; do 228 mkdir -p $i/dirchange/$j 229 done 230 done 231 232 # /dirchange/fromdir/extradir: Convert a directory tree to a 233 # file. The test tree includes an extra file in the directory 234 # that is not present in the old tree. This should generate a 235 # warning. 236 for i in $OLD $TEST; do 237 mkdir $i/dirchange/fromdir/extradir 238 echo "foo" > $i/dirchange/fromdir/extradir/file 239 done 240 mkfifo $TEST/dirchange/fromdir/extradir/fifo 241 ln -s "bar" $NEW/dirchange/fromdir/extradir 242 243 # /dirchange/fromdir/conflict: Convert a directory tree to a 244 # file. The test tree includes a local change that generates 245 # a warning and prevents the removal of the directory. 246 for i in $OLD $TEST; do 247 mkdir $i/dirchange/fromdir/conflict 248 done 249 echo "foo" > $OLD/dirchange/fromdir/conflict/somefile 250 echo "bar" > $TEST/dirchange/fromdir/conflict/somefile 251 mkfifo $NEW/dirchange/fromdir/conflict 252 253 # /dirchange/todir/difffile: Convert a file to a directory 254 # tree. The test tree has a locally modified version of the 255 # file so that the conversion fails with a warning. 256 echo "foo" > $OLD/dirchange/todir/difffile 257 mkdir $NEW/dirchange/todir/difffile 258 echo "baz" > $NEW/dirchange/todir/difffile/file 259 echo "bar" > $TEST/dirchange/todir/difffile 260 261 # /dirchange/todir/difftype: Similar to the previous test, but 262 # the conflict is due to a change in the file type. 263 echo "foo" > $OLD/dirchange/todir/difftype 264 mkdir $NEW/dirchange/todir/difftype 265 echo "baz" > $NEW/dirchange/todir/difftype/file 266 mkfifo $TEST/dirchange/todir/difftype 267} 268 269# $1 - relative path to file that should be missing from TEST 270missing() 271{ 272 if [ -e $TEST/$1 -o -L $TEST/$1 ]; then 273 echo "File $1 should be missing" 274 fi 275} 276 277# $1 - relative path to file that should be present in TEST 278present() 279{ 280 if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then 281 echo "File $1 should be present" 282 fi 283} 284 285# $1 - relative path to file that should be a fifo in TEST 286fifo() 287{ 288 if ! [ -p $TEST/$1 ]; then 289 echo "File $1 should be a FIFO" 290 fi 291} 292 293# $1 - relative path to file that should be a directory in TEST 294dir() 295{ 296 if ! [ -d $TEST/$1 ]; then 297 echo "File $1 should be a directory" 298 fi 299} 300 301# $1 - relative path to file that should be a symlink in TEST 302# $2 - optional value of the link 303link() 304{ 305 local val 306 307 if ! [ -L $TEST/$1 ]; then 308 echo "File $1 should be a link" 309 elif [ $# -gt 1 ]; then 310 val=`readlink $TEST/$1` 311 if [ "$val" != "$2" ]; then 312 echo "Link $1 should link to \"$2\"" 313 fi 314 fi 315} 316 317# $1 - relative path to regular file that should be present in TEST 318# $2 - optional string that should match file contents 319# $3 - optional MD5 of the flie contents, overrides $2 if present 320file() 321{ 322 local contents sum 323 324 if ! [ -f $TEST/$1 ]; then 325 echo "File $1 should be a regular file" 326 elif [ $# -eq 2 ]; then 327 contents=`cat $TEST/$1` 328 if [ "$contents" != "$2" ]; then 329 echo "File $1 has wrong contents" 330 fi 331 elif [ $# -eq 3 ]; then 332 sum=`md5 -q $TEST/$1` 333 if [ "$sum" != "$3" ]; then 334 echo "File $1 has wrong contents" 335 fi 336 fi 337} 338 339# $1 - relative path to a regular file that should have a conflict 340# $2 - optional MD5 of the conflict file contents 341conflict() 342{ 343 local sum 344 345 if ! [ -f $CONFLICTS/$1 ]; then 346 echo "File $1 missing conflict" 347 elif [ $# -gt 1 ]; then 348 sum=`md5 -q $CONFLICTS/$1` 349 if [ "$sum" != "$2" ]; then 350 echo "Conflict $1 has wrong contents" 351 fi 352 fi 353} 354 355# $1 - relative path to a regular file that should not have a conflict 356noconflict() 357{ 358 if [ -f $CONFLICTS/$1 ]; then 359 echo "File $1 should not have a conflict" 360 fi 361} 362 363if [ `id -u` -ne 0 ]; then 364 echo "must be root" 365fi 366 367if [ -r /etc/etcupdate.conf ]; then 368 echo "WARNING: /etc/etcupdate.conf settings may break some tests." 369fi 370 371# First run the test ignoring no patterns. 372 373build_trees 374 375etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out 376 377cat > $WORKDIR/correct.out <<EOF 378 D /dirchange/fromdir/extradir/file 379 C /difffiles/difffiles/difffiles/conflict 380 C /difftype/difftype/difffiles/file 381 C /second/second/difffiles/file 382Warnings: 383 Modified regular file remains: /dirchange/fromdir/conflict/somefile 384 Modified regular file remains: /first/difffiles/second/file 385 Modified symbolic link remains: /first/difflinks/second/link 386 Modified directory remains: /first/difftype/second/fifo 387 Modified directory remains: /rmdir/conflict/difftype 388 Non-empty directory remains: /rmdir/extra 389 Non-empty directory remains: /rmdir/conflict 390 Modified mismatch: /difffiles/difftype/difftype/file (regular file vs fifo file) 391 Removed file changed: /difffiles/first/first/file 392 Modified link changed: /difflinks/difflinks/difflinks/link ("old" became "new") 393 Modified mismatch: /difflinks/difftype/difftype/link (symbolic link vs regular file) 394 Removed link changed: /difflinks/first/first/link ("old" became "new") 395 New link conflict: /difftype/difftype/difflinks/link ("new" vs "test") 396 Modified regular file changed: /difftype/difftype/difftype/one (fifo file became directory) 397 Modified symbolic link changed: /difftype/difftype/difftype/two (directory became regular file) 398 Remove mismatch: /difftype/first/first/fifo (fifo file became directory) 399 Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file) 400 Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link) 401 Modified regular file changed: /dirchange/todir/difffile (regular file became directory) 402 Modified fifo file changed: /dirchange/todir/difftype (regular file became directory) 403 New file mismatch: /adddir/conflict (directory vs regular file) 404 Directory mismatch: $TEST/adddir/conflict (regular file) 405 Directory mismatch: $TEST/dirchange/todir/difffile (regular file) 406 Directory mismatch: $TEST/dirchange/todir/difftype (fifo file) 407 New link conflict: /second/second/difflinks/link ("new link" vs "test link") 408 New file mismatch: /second/second/difftype/dir (directory vs fifo file) 409EOF 410 411echo "Differences for regular:" 412diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out 413 414## /first/difftype/second: 415present /first/difftype/second/fifo 416 417## /first/difflinks/second: 418link /first/difflinks/second/link "test link" 419 420## /first/difffiles/second: 421file /first/difffiles/second/file "bar" 422 423## /second/second/difftype: 424fifo /second/second/difftype/dir 425 426## /second/second/difflinks: 427link /second/second/difflinks/link "test link" 428 429## /second/second/difffiles: 430file /second/second/difffiles/file "test" 431conflict /second/second/difffiles/file 4f2ee8620a251fd53f06bb6112eb6ffa 432 433## /difftype/first/first: 434missing /difftype/first/first/fifo 435 436## /difftype/difftype/difftype: 437file /difftype/difftype/difftype/one "foo" 438link /difftype/difftype/difftype/two "bar" 439 440## /difftype/difftype/difflinks: 441link /difftype/difftype/difflinks/link "test" 442 443## /difftype/difftype/difffile: 444conflict /difftype/difftype/difffiles/file 117f2bcd1f6491f6044e79e5a57a9229 445 446## /difflinks/first/first: 447missing /difflinks/first/first/link 448 449## /difflinks/difftype/difftype: 450file /difflinks/difftype/difftype/link "test" 451 452## /difflinks/difflinks/difflinks: 453link /difflinks/difflinks/difflinks/link "test" 454 455## /difffiles/first/first: 456missing /difffiles/first/first/file 457 458## /difffiles/difftype/difftype: 459fifo /difffiles/difftype/difftype/file 460 461## /difffiles/difffiles/difffiles: 462file /difffiles/difffiles/difffiles/conflict "this is a test file" 463conflict /difffiles/difffiles/difffiles/conflict \ 464 8261cfdd89280c4a6c26e4ac86541fe9 465 466## /adddir/conflict: 467file /adddir/conflict 468 469## /rmdir/extra: 470dir /rmdir/extra 471file /rmdir/extra/localfile.txt "foo" 472 473## /rmdir/conflict: 474dir /rmdir/conflict/difftype 475present /rmdir/conflict 476 477## /dirchange/fromdir/extradir: 478missing /dirchange/fromdir/extradir/file 479fifo /dirchange/fromdir/extradir/fifo 480 481## /dirchange/fromdir/conflict: 482file /dirchange/fromdir/conflict/somefile "bar" 483 484## /dirchange/todir/difffile: 485file /dirchange/todir/difffile "bar" 486 487## /dirchange/todir/difftype: 488fifo /dirchange/todir/difftype 489 490# Now test with -A '/first*' -A '/second* /*di*'. This should remove 491# most of the warnings and conflicts. 492 493build_trees 494 495etcupdate -r -A '/first*' -A '/second* /*di*' -d $WORKDIR -D $TEST > \ 496 $WORKDIR/test1.out 497 498cat > $WORKDIR/correct1.out <<EOF 499 D /dirchange/fromdir/extradir/file 500 U /difffiles/difffiles/difffiles/conflict 501 U /difffiles/difftype/difftype/file 502 A /difffiles/first/first/file 503 U /difflinks/difflinks/difflinks/link 504 U /difflinks/difftype/difftype/link 505 A /difflinks/first/first/link 506 U /difftype/difftype/difffiles/file 507 U /difftype/difftype/difflinks/link 508 D /difftype/difftype/difftype/one 509 U /difftype/difftype/difftype/two 510 U /dirchange/todir/difffile 511 U /dirchange/todir/difftype 512 U /adddir/conflict 513 A /adddir/conflict/newfile 514 A /dirchange/todir/difffile/file 515 A /dirchange/todir/difftype/file 516 U /second/second/difffiles/file 517 U /second/second/difflinks/link 518 D /second/second/difftype/dir 519Warnings: 520 Modified regular file remains: /dirchange/fromdir/conflict/somefile 521 Modified regular file remains: /first/difffiles/second/file 522 Modified symbolic link remains: /first/difflinks/second/link 523 Modified directory remains: /first/difftype/second/fifo 524 Modified directory remains: /rmdir/conflict/difftype 525 Non-empty directory remains: /rmdir/extra 526 Non-empty directory remains: /rmdir/conflict 527 Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file) 528 Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link) 529EOF 530 531echo "Differences for -A '/first*' -A '/second* /*di*':" 532diff -u -L "correct" $WORKDIR/correct1.out -L "test" $WORKDIR/test1.out 533 534## /first/difftype/second: 535present /first/difftype/second/fifo 536 537## /first/difflinks/second: 538link /first/difflinks/second/link "test link" 539 540## /first/difffiles/second: 541file /first/difffiles/second/file "bar" 542 543## /second/second/difftype: 544missing /second/second/difftype/dir 545 546## /second/second/difflinks: 547link /second/second/difflinks/link "new link" 548 549## /second/second/difffiles: 550file /second/second/difffiles/file "new" 551noconflict /second/second/difffiles/file 552 553## /difftype/first/first: 554missing /difftype/first/first/fifo 555 556## /difftype/difftype/difftype: 557missing /difftype/difftype/difftype/one 558file /difftype/difftype/difftype/two "baz" 559 560## /difftype/difftype/difflinks: 561link /difftype/difftype/difflinks/link "new" 562 563## /difftype/difftype/difffile: 564noconflict /difftype/difftype/difffiles/file 565file /difftype/difftype/difffiles/file "foo" 566 567## /difflinks/first/first: 568link /difflinks/first/first/link "new" 569 570## /difflinks/difftype/difftype: 571link /difflinks/difftype/difftype/link "new" 572 573## /difflinks/difflinks/difflinks: 574link /difflinks/difflinks/difflinks/link "new" 575 576## /difffiles/first/first: 577file /difffiles/first/first/file "bar" 578 579## /difffiles/difftype/difftype: 580file /difffiles/difftype/difftype/file "new" 581 582## /difffiles/difffiles/difffiles: 583noconflict /difffiles/difffiles/difffiles/conflict 584file /difffiles/difffiles/difffiles/conflict "this is a new file" 585 586## /adddir/conflict: 587file /adddir/conflict/newfile 588 589## /rmdir/extra: 590dir /rmdir/extra 591file /rmdir/extra/localfile.txt "foo" 592 593## /rmdir/conflict: 594dir /rmdir/conflict/difftype 595present /rmdir/conflict 596 597## /dirchange/fromdir/extradir: 598missing /dirchange/fromdir/extradir/file 599fifo /dirchange/fromdir/extradir/fifo 600 601## /dirchange/fromdir/conflict: 602file /dirchange/fromdir/conflict/somefile "bar" 603 604## /dirchange/todir/difffile: 605file /dirchange/todir/difffile/file "baz" 606 607## /dirchange/todir/difftype: 608file /dirchange/todir/difftype/file "baz" 609