Home | History | Annotate | Line # | Download | only in mtree
      1 # $NetBSD: t_mtree.sh,v 1.10 2023/12/02 16:18:17 christos Exp $
      2 #
      3 # Copyright (c) 2009, 2012 The NetBSD Foundation, Inc.
      4 # All rights reserved.
      5 #
      6 # Redistribution and use in source and binary forms, with or without
      7 # modification, are permitted provided that the following conditions
      8 # are met:
      9 # 1. Redistributions of source code must retain the above copyright
     10 #    notice, this list of conditions and the following disclaimer.
     11 # 2. Redistributions in binary form must reproduce the above copyright
     12 #    notice, this list of conditions and the following disclaimer in the
     13 #    documentation and/or other materials provided with the distribution.
     14 #
     15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25 # POSSIBILITY OF SUCH DAMAGE.
     26 #
     27 
     28 # Postprocess mtree output, canonicalising portions that
     29 # are expected to differ from one run to another.
     30 #
     31 
     32 h_postprocess()
     33 {
     34 	sed -e '
     35 		/^#	   user: /s/:.*/: x/
     36 		/^#	machine: /s/:.*/: x/
     37 		/^#	   tree: /s/:.*/: x/
     38 		/^#	   date: /s/:.*/: x/
     39 		' \
     40 	    -e '/type=dir/s/ size=[0-9]*//'
     41 }
     42 
     43 h_check()
     44 {
     45         diff -Nru "$1" "$2" || atf_fail "files $1 and $2 differ"
     46 }
     47 
     48 
     49 atf_test_case mtree_create
     50 atf_test_case netbsd6_create
     51 create_head()
     52 {
     53 	atf_set "descr" "Create a specfile describing a directory tree"
     54 }
     55 
     56 create_setup()
     57 {
     58 	# create some directories
     59 	rm -fr create
     60 	mkdir -p create/a/1 create/a/2 create/b
     61 	# create some files
     62 	for file in create/top.file.1 \
     63 		    create/a/a.file.1 \
     64 		    create/a/a.file.2 \
     65 		    create/a/1/a1.file.1 \
     66 		    create/b/b.file.1 \
     67 		    create/b/b.file.2
     68 	do
     69 		echo "$file" >$file
     70 	done
     71 	# hard link to file in same dir
     72 	ln create/b/b.file.1 create/b/b.hardlink.1
     73 	# hard link to file in another dir
     74 	ln create/b/b.file.2 create/a/a.hardlink.b2
     75 	# symlink to file
     76 	ln -s a.file.1 create/a.symlink.1
     77 	# symlink to dir
     78 	ln -s b create/top.symlink.b
     79 	# dangling symlink
     80 	ln -s nonexistent create/top.dangling
     81 }
     82 
     83 create_body()
     84 {
     85 	create_setup
     86 
     87 	# run mtree and check output
     88 	( cd create && mtree -F ${FLAVOR} -c -k type,nlink,link,size,sha256 ) >output.raw \
     89 	|| atf_fail "mtree exit status $?"
     90 	h_postprocess <output.raw >output
     91 	h_check "$(atf_get_srcdir)/${FLAVOR}_d_create.out" output
     92 }
     93 
     94 mtree_create_head() 
     95 {
     96 	FLAVOR=mtree create_head
     97 }
     98 netbsd6_create_head() 
     99 {
    100 	FLAVOR=netbsd6 create_head
    101 }
    102 
    103 mtree_create_body() 
    104 {
    105 	FLAVOR=mtree create_body
    106 }
    107 netbsd6_create_body() 
    108 {
    109 	FLAVOR=netbsd6 create_body
    110 }
    111 
    112 
    113 atf_test_case mtree_check
    114 atf_test_case netbsd6_check
    115 check_head()
    116 {
    117 	atf_set "descr" "Check a directory tree against a specfile"
    118 }
    119 
    120 check_body()
    121 {
    122 	# we use the same directory tree and specfile as in the "create" test
    123 	create_setup
    124 
    125 	# run mtree and check output
    126 	( cd create && mtree -F ${FLAVOR}  ) <"$(atf_get_srcdir)/${FLAVOR}_d_create.out" >output \
    127 	|| atf_fail "mtree exit status $?"
    128 	h_check /dev/null output
    129 }
    130 
    131 mtree_check_head() 
    132 {
    133 	FLAVOR=mtree check_head
    134 }
    135 netbsd6_check_head() 
    136 {
    137 	FLAVOR=netbsd6 check_head
    138 }
    139 
    140 mtree_check_body() 
    141 {
    142 	FLAVOR=mtree check_body
    143 }
    144 netbsd6_check_body() 
    145 {
    146 	FLAVOR=netbsd6 check_body
    147 }
    148 
    149 
    150 atf_test_case mtree_convert_C
    151 atf_test_case netbsd6_convert_C
    152 convert_C_head()
    153 {
    154 	atf_set "descr" "Convert a specfile to mtree -C format, unsorted"
    155 }
    156 
    157 convert_C_body()
    158 {
    159 	mtree -F ${FLAVOR} -C -K all <"$(atf_get_srcdir)/d_convert.in" >output
    160 	h_check "$(atf_get_srcdir)/d_convert_C.out" output
    161 }
    162 
    163 mtree_convert_C_head() 
    164 {
    165 	FLAVOR=mtree convert_C_head
    166 }
    167 netbsd6_convert_C_head() 
    168 {
    169 	FLAVOR=netbsd6 convert_C_head
    170 }
    171 
    172 mtree_convert_C_body() 
    173 {
    174 	FLAVOR=mtree convert_C_body
    175 }
    176 netbsd6_convert_C_body() 
    177 {
    178 	FLAVOR=netbsd6 convert_C_body
    179 }
    180 
    181 
    182 atf_test_case mtree_convert_C_S
    183 atf_test_case netbsd6_convert_C_S
    184 convert_C_S_head()
    185 {
    186 	atf_set "descr" "Convert a specfile to mtree -C format, sorted"
    187 }
    188 
    189 convert_C_S_body()
    190 {
    191 	mtree -F ${FLAVOR} -C -S -K all <"$(atf_get_srcdir)/d_convert.in" >output
    192 	h_check "$(atf_get_srcdir)/d_convert_C_S.out" output
    193 }
    194 
    195 mtree_convert_C_S_head() 
    196 {
    197 	FLAVOR=mtree convert_C_S_head
    198 }
    199 netbsd6_convert_C_S_head() 
    200 {
    201 	FLAVOR=netbsd6 convert_C_S_head
    202 }
    203 
    204 mtree_convert_C_S_body() 
    205 {
    206 	FLAVOR=mtree convert_C_S_body
    207 }
    208 netbsd6_convert_C_S_body() 
    209 {
    210 	FLAVOR=netbsd6 convert_C_S_body
    211 }
    212 
    213 
    214 atf_test_case mtree_convert_D
    215 atf_test_case netbsd6_convert_D
    216 convert_D_head()
    217 {
    218 	atf_set "descr" "Convert a specfile to mtree -D format, unsorted"
    219 }
    220 
    221 convert_D_body()
    222 {
    223 	mtree -F ${FLAVOR} -D -K all <"$(atf_get_srcdir)/d_convert.in" >output
    224 	h_check "$(atf_get_srcdir)/d_convert_D.out" output
    225 }
    226 
    227 mtree_convert_D_head() 
    228 {
    229 	FLAVOR=mtree convert_D_head
    230 }
    231 netbsd6_convert_D_head() 
    232 {
    233 	FLAVOR=netbsd6 convert_D_head
    234 }
    235 
    236 mtree_convert_D_body() 
    237 {
    238 	FLAVOR=mtree convert_D_body
    239 }
    240 netbsd6_convert_D_body() 
    241 {
    242 	FLAVOR=netbsd6 convert_D_body
    243 }
    244 
    245 
    246 atf_test_case mtree_convert_D_S
    247 atf_test_case netbsd6_convert_D_S
    248 convert_D_S_head()
    249 {
    250 	atf_set "descr" "Convert a specfile to mtree -D format, sorted"
    251 }
    252 
    253 convert_D_S_body()
    254 {
    255 	mtree -F ${FLAVOR} -D -S -K all <"$(atf_get_srcdir)/d_convert.in" >output
    256 	h_check "$(atf_get_srcdir)/d_convert_D_S.out" output
    257 }
    258 
    259 mtree_convert_D_S_head() 
    260 {
    261 	FLAVOR=mtree convert_D_S_head
    262 }
    263 netbsd6_convert_D_S_head() 
    264 {
    265 	FLAVOR=netbsd6 convert_D_S_head
    266 }
    267 
    268 mtree_convert_D_S_body() 
    269 {
    270 	FLAVOR=mtree convert_D_S_body
    271 }
    272 netbsd6_convert_D_S_body() 
    273 {
    274 	FLAVOR=netbsd6 convert_D_S_body
    275 }
    276 
    277 
    278 atf_test_case mtree_ignore
    279 atf_test_case netbs6_ignore
    280 ignore_head()
    281 {
    282 	atf_set "descr" "Test that -d ignores symlinks (PR bin/41061)"
    283 }
    284 
    285 ignore_body()
    286 {
    287 	# Kyua 0.11 and above point TMPDIR to our work directory and atf-check
    288 	# generates a temporary file, which confuses mtree.  Put the mtree files
    289 	# into a subdirectory.
    290 	#
    291 	# See https://github.com/jmmv/kyua/issues/133 for details.
    292 	mkdir root && cd root
    293 
    294 	mkdir newdir
    295 	mtree -F ${FLAVOR} -c | mtree -F ${FLAVOR} -Ck uid,gid,mode > mtree.spec
    296 	ln -s newdir otherdir
    297 
    298 	# This yields "extra: otherdir" even with -d.
    299 	# (PR bin/41061)
    300 	atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec"
    301 
    302 	# Delete the symlink and re-verify.
    303 	#
    304 	rm otherdir
    305 	atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec"
    306 }
    307 
    308 mtree_ignore_head() 
    309 {
    310 	FLAVOR=mtree ignore_head
    311 }
    312 netbsd6_ignore_head() 
    313 {
    314 	FLAVOR=netbsd6 ignore_head
    315 }
    316 
    317 mtree_ignore_body() 
    318 {
    319 	FLAVOR=mtree ignore_body
    320 }
    321 netbsd6_ignore_body() 
    322 {
    323 	# Kyua 0.11 and above point TMPDIR to our work directory and atf-check
    324 	# generates a temporary file, which confuses mtree.  Put the mtree files
    325 	# into a subdirectory.
    326 	#
    327 	# See https://github.com/jmmv/kyua/issues/133 for details.
    328 	mkdir root && cd root
    329 
    330 	FLAVOR=netbsd6 ignore_body
    331 }
    332 
    333 
    334 atf_test_case mtree_merge
    335 atf_test_case netbsd6_merge
    336 merge_head()
    337 {
    338 	atf_set "descr" "Merge records of different type"
    339 }
    340 
    341 merge_body()
    342 {
    343 	mtree -F ${FLAVOR} -C -M -K all <"$(atf_get_srcdir)/d_merge.in" >output
    344 	h_check "$(atf_get_srcdir)/d_merge_C_M.out" output
    345 	# same again, with sorting
    346 	mtree -F ${FLAVOR} -C -M -S -K all <"$(atf_get_srcdir)/d_merge.in" >output
    347 	h_check "$(atf_get_srcdir)/d_merge_C_M_S.out" output
    348 }
    349 
    350 mtree_merge_head() 
    351 {
    352 	FLAVOR=mtree merge_head
    353 }
    354 netbsd6_merge_head() 
    355 {
    356 	FLAVOR=netbsd6 merge_head
    357 }
    358 
    359 mtree_merge_body() 
    360 {
    361 	FLAVOR=mtree merge_body
    362 }
    363 netbsd6_merge_body() 
    364 {
    365 	FLAVOR=netbsd6 merge_body
    366 }
    367 
    368 
    369 atf_test_case mtree_nonemptydir
    370 atf_test_case netbsd6_nonemptydir
    371 nonemptydir_head()
    372 {
    373 	atf_set "descr" "Test that new non-empty " \
    374 			"directories are recorded (PR bin/25693)"
    375 }
    376 
    377 nonemptydir_body()
    378 {
    379 	mkdir testdir
    380 	cd testdir
    381 
    382 	mtree -F ${FLAVOR} -c > mtree.spec
    383 
    384 	if [ ! -f mtree.spec ]; then
    385 		atf_fail "mtree failed"
    386 	fi
    387 
    388 	touch bar
    389 	atf_check -s ignore -o save:output -x "mtree -F ${FLAVOR} -f mtree.spec"
    390 
    391 	if [ ! -n "$(egrep "extra: bar" output)" ]; then
    392 		atf_fail "mtree did not record changes (PR bin/25693)"
    393 	fi
    394 }
    395 
    396 mtree_nonemptydir_head() 
    397 {
    398 	FLAVOR=mtree nonemptydir_head
    399 }
    400 netbsd6_nonemptydir_head() 
    401 {
    402 	FLAVOR=netbsd6 nonemptydir_head
    403 }
    404 
    405 mtree_nonemptydir_body() 
    406 {
    407 	FLAVOR=mtree nonemptydir_body
    408 }
    409 netbsd6_nonemptydir_body() 
    410 {
    411 	FLAVOR=netbsd6 nonemptydir_body
    412 }
    413 
    414 atf_test_case mtree_specspec_type
    415 mtree_specspec_type_head()
    416 {
    417 	atf_set "descr" "Test that spec comparisons detect type changes"
    418 }
    419 
    420 mtree_specspec_type_body()
    421 {
    422 	mkdir testdir
    423 
    424 	touch testdir/bar
    425 	mtree -c -p testdir > mtree1.spec
    426 
    427 	if [ ! -f mtree1.spec ]; then
    428 		atf_fail "mtree failed"
    429 	fi
    430 
    431 	rm -f testdir/bar
    432 	ln -s foo testdir/bar
    433 	# uid change is expected to be ignored as done in -C
    434 	chown -h operator testdir/bar
    435 	mtree -c -p testdir > mtree2.spec
    436 
    437 	if [ ! -f mtree2.spec ]; then
    438 		atf_fail "mtree failed"
    439 	fi
    440 
    441 	atf_check -s ignore -o save:output \
    442 	    -x "mtree -f mtree1.spec -f mtree2.spec"
    443 
    444 	if ! cut -f 3 output | egrep -q "bar file" || \
    445 	    ! cut -f 3 output | egrep -q "bar link"; then
    446 		atf_fail "mtree did not detect type change"
    447 	fi
    448 }
    449 
    450 atf_test_case mtree_onlyfile
    451 atf_test_case netbsd6_onlyfile
    452 onlyfile_head()
    453 {
    454 	atf_set "descr" "Test -O with same hash value in directory and leaf"
    455 }
    456 
    457 onlyfile_body()
    458 {
    459 	mkdir -p ab/no
    460 	echo ./ab/no >onlyfile
    461 	mtree -F ${FLAVOR} -c -n -O onlyfile >output
    462 	if [ ! -s output ]; then
    463 		atf_fail "mtree did not find path in onlyfile"
    464 	fi
    465 }
    466 
    467 mtree_onlyfile_head()
    468 {
    469 	FLAVOR=mtree onlyfile_head
    470 }
    471 netbsd6_onlyfile_head()
    472 {
    473 	FLAVOR=netbsd6 onlyfile_head
    474 }
    475 
    476 mtree_onlyfile_body()
    477 {
    478 	FLAVOR=mtree onlyfile_body
    479 }
    480 netbsd6_onlyfile_body()
    481 {
    482 	FLAVOR=netbsd6 onlyfile_body
    483 }
    484 
    485 
    486 atf_init_test_cases()
    487 {
    488 	atf_add_test_case mtree_create
    489 	atf_add_test_case mtree_check
    490 	atf_add_test_case mtree_convert_C
    491 	atf_add_test_case mtree_convert_C_S
    492 	atf_add_test_case mtree_convert_D
    493 	atf_add_test_case mtree_convert_D_S
    494 	atf_add_test_case mtree_ignore
    495 	atf_add_test_case mtree_merge
    496 	atf_add_test_case mtree_nonemptydir
    497 	atf_add_test_case mtree_specspec_type
    498 	atf_add_test_case mtree_onlyfile
    499 
    500 	atf_add_test_case netbsd6_create
    501 	atf_add_test_case netbsd6_check
    502 	atf_add_test_case netbsd6_convert_C
    503 	atf_add_test_case netbsd6_convert_C_S
    504 	atf_add_test_case netbsd6_convert_D
    505 	atf_add_test_case netbsd6_convert_D_S
    506 	atf_add_test_case netbsd6_ignore
    507 	atf_add_test_case netbsd6_merge
    508 	atf_add_test_case netbsd6_nonemptydir
    509 	atf_add_test_case netbsd6_onlyfile
    510 }
    511