1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2023 The FreeBSD Foundation 4# 5# This software was developed1 by Yan-Hao Wang <bses30074@gmail.com> 6# under sponsorship from the FreeBSD Foundation. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30. $(atf_get_srcdir)/conf.sh 31 32atf_test_case create cleanup 33create_head() 34{ 35 atf_set "descr" "Test gunion create and destroy" 36 atf_set "require.user" "root" 37} 38create_body() 39{ 40 gunion_test_setup 41 42 attach_md upperdev -s 1m 43 attach_md lowerdev -s 1m 44 newfs -U "/dev/${lowerdev}" 45 46 atf_check gunion create "$upperdev" "$lowerdev" 47 guniondev="${upperdev}-${lowerdev}.union" 48 atf_check -o inline:"/dev/${guniondev}\n" ls "/dev/${guniondev}" 49 atf_check -o ignore fsck -p -f "/dev/${guniondev}" 50 51 atf_check gunion destroy "$guniondev" 52 atf_check -s not-exit:0 -o ignore -e ignore ls "/dev/${guniondev}" 53} 54create_cleanup() 55{ 56 gunion_test_cleanup 57} 58 59atf_test_case basic cleanup 60basic_head() 61{ 62 atf_set "descr" "Check gunion doesn't affect lowerdev status and lowerdev can't be mounted when being in a gunion" 63 atf_set "require.user" "root" 64} 65basic_body() 66{ 67 gunion_test_setup 68 69 attach_md upperdev -s 1m 70 attach_md lowerdev -s 1m 71 newfs -U "/dev/${lowerdev}" 72 mkdir lowermnt 73 mkdir gunionmnt 74 75 mount "/dev/${lowerdev}" lowermnt 76 echo "lower file" > lower_file 77 cp lower_file lowermnt/lower_file 78 sync 79 umount lowermnt 80 81 gunion create "$upperdev" "$lowerdev" 82 guniondev="${upperdev}-${lowerdev}.union" 83 atf_check -s not-exit:0 -o ignore -e ignore mount "/dev/${lowerdev}" lowermnt 84 85 mount "/dev/${guniondev}" gunionmnt 86 echo "update lower file" >> gunionmnt/lower_file 87 echo "gunion file" > gunion_file 88 cp gunion_file gunionmnt/gunion_file 89 sync 90 umount gunionmnt 91 92 gunion destroy "$guniondev" 93 mount "/dev/${lowerdev}" lowermnt 94 checksum lowermnt/lower_file lower_file 95 atf_check -s not-exit:0 -o ignore -e ignore ls lowermnt/gunion_file 96} 97basic_cleanup() 98{ 99 gunion_test_cleanup 100} 101 102atf_test_case commit cleanup 103commit_head() 104{ 105 atf_set "descr" "Test basic gunion commit without option" 106 atf_set "require.user" "root" 107} 108commit_body() 109{ 110 gunion_test_setup 111 112 attach_md upperdev -s 1m 113 attach_md lowerdev -s 1m 114 newfs -U "/dev/${lowerdev}" 115 mkdir lowermnt 116 mkdir gunionmnt 117 118 mount "/dev/${lowerdev}" lowermnt 119 echo "lower file" > lower_file 120 cp lower_file lowermnt/lower_file 121 sync 122 umount lowermnt 123 124 gunion create "$upperdev" "$lowerdev" 125 guniondev="${upperdev}-${lowerdev}.union" 126 mount "/dev/${guniondev}" gunionmnt 127 checksum gunionmnt/lower_file lower_file 128 129 echo "update lower file" >> lower_file 130 cp -f lower_file gunionmnt/lower_file 131 echo "gunion file" > gunion_file 132 cp gunion_file gunionmnt/gunion_file 133 sync 134 umount gunionmnt 135 atf_check gunion commit "$guniondev" 136 gunion destroy "$guniondev" 137 138 atf_check -o ignore fsck -p -f "/dev/${lowerdev}" 139 mount "/dev/${lowerdev}" lowermnt 140 checksum lowermnt/lower_file lower_file 141 checksum lowermnt/gunion_file gunion_file 142} 143commit_cleanup() 144{ 145 gunion_test_cleanup 146} 147 148atf_test_case offset cleanup 149offset_head() 150{ 151 atf_set "descr" "Test gunion create with -o offset option" 152 atf_set "require.user" "root" 153} 154offset_body() 155{ 156 gunion_test_setup 157 158 attach_md upperdev -s 1m 159 attach_md lowerdev -s 1m 160 gpart create -s GPT "/dev/${lowerdev}" 161 gpart add -t freebsd-ufs "$lowerdev" 162 newfs "/dev/${lowerdev}p1" 163 gpt_entry_1=$(gpart show "/dev/${lowerdev}") 164 mkdir gunionmnt 165 166 secsize="$(diskinfo "/dev/${lowerdev}" | awk '{print $2}')" 167 p1_start_sector="$(gpart show -p "/dev/${lowerdev}" | grep ${lowerdev}p1 | awk '{print $1}')" 168 offset_size="$((secsize * p1_start_sector))" 169 170 gunion create -o "$offset_size" "$upperdev" "$lowerdev" 171 guniondev="${upperdev}-${lowerdev}.union" 172 173 atf_check -o ignore fsck -p -f "/dev/${guniondev}" 174 atf_check mount "/dev/${guniondev}" gunionmnt 175 umount gunionmnt 176 gunion destroy "$guniondev" 177 178 gpt_entry_2=$(gpart show "/dev/${lowerdev}") 179 atf_check_equal "$gpt_entry_1" "$gpt_entry_2" 180} 181offset_cleanup() 182{ 183 gunion_test_cleanup 184} 185 186atf_test_case size cleanup 187size_head() 188{ 189 atf_set "descr" "Test gunion create with -s size option" 190 atf_set "require.user" "root" 191} 192size_body() 193{ 194 gunion_test_setup 195 196 attach_md upperdev -s 2m 197 attach_md lowerdev -s 1m 198 newfs -U "/dev/${lowerdev}" 199 200 gunion create -s 2m "$upperdev" "$lowerdev" 201 guniondev="${upperdev}-${lowerdev}.union" 202 echo "$guniondev" > guniondev 203 204 size="$(diskinfo "/dev/$guniondev" | awk '{print $3}')" 205 atf_check_equal "2097152" "$size" # 2 MB = 2097152 bytes 206} 207size_cleanup() 208{ 209 gunion_test_cleanup 210} 211 212atf_test_case secsize cleanup 213secsize_head() 214{ 215 atf_set "descr" "Test gunion create with -S secsize option" 216 atf_set "require.user" "root" 217} 218secsize_body() 219{ 220 gunion_test_setup 221 222 attach_md upperdev -s 1m 223 attach_md lowerdev -s 1m 224 newfs -S 512 -U "/dev/${lowerdev}" 225 lower_secsize="$(diskinfo "/dev/${lowerdev}" | awk '{print $2}')" 226 atf_check_equal "512" "$lower_secsize" 227 228 gunion create -S 1024 "$upperdev" "$lowerdev" 229 guniondev="${upperdev}-${lowerdev}.union" 230 echo "$guniondev" > guniondev 231 232 secsize="$(diskinfo "/dev/${guniondev}" | awk '{print $2}')" 233 atf_check_equal "1024" "$secsize" 234} 235secsize_cleanup() 236{ 237 gunion_test_cleanup 238} 239 240atf_test_case gunionname cleanup 241gunionname_head() 242{ 243 atf_set "descr" "Test gunion create with -Z gunionname option" 244 atf_set "require.user" "root" 245} 246gunionname_body() 247{ 248 gunion_test_setup 249 250 attach_md upperdev -s 1m 251 attach_md lowerdev -s 1m 252 newfs -U "/dev/${lowerdev}" 253 254 gunion create -Z gunion1 "$upperdev" "$lowerdev" 255 echo "gunion1.union" > guniondev 256 atf_check -o inline:"/dev/gunion1.union\n" ls /dev/gunion1.union 257} 258gunionname_cleanup() 259{ 260 gunion_test_cleanup 261} 262 263atf_test_case revert cleanup 264revert_head() 265{ 266 atf_set "descr" "Test gunion revert" 267 atf_set "require.user" "root" 268} 269revert_body() 270{ 271 gunion_test_setup 272 273 attach_md upperdev -s 1m 274 attach_md lowerdev -s 1m 275 newfs -U "/dev/${lowerdev}" 276 mkdir lowermnt 277 mkdir gunionmnt 278 279 mount "/dev/${lowerdev}" lowermnt 280 echo "lower file" > lower_file 281 cp lower_file lowermnt/lower_file 282 sync 283 umount lowermnt 284 285 atf_check gunion create "$upperdev" "$lowerdev" 286 guniondev="${upperdev}-${lowerdev}.union" 287 mount "/dev/${guniondev}" gunionmnt 288 289 echo "update lower file" >> gunionmnt/lower_file 290 echo "gunion file" > gunion_file 291 cp gunion_file gunionmnt/gunion_file 292 sync 293 umount gunionmnt 294 atf_check gunion revert "$guniondev" 295 296 mount "/dev/${guniondev}" gunionmnt 297 checksum gunionmnt/lower_file lower_file 298 atf_check -s not-exit:0 -o ignore -e ignore ls gunionmnt/gunion_file 299 300 umount gunionmnt 301 gunion destroy "$guniondev" 302} 303revert_cleanup() 304{ 305 gunion_test_cleanup 306} 307 308atf_init_test_cases() 309{ 310 atf_add_test_case create 311 atf_add_test_case basic 312 atf_add_test_case commit 313 atf_add_test_case offset 314 atf_add_test_case size 315 atf_add_test_case secsize 316 atf_add_test_case gunionname 317 atf_add_test_case revert 318} 319 320checksum() 321{ 322 src=$1 323 work=$2 324 325 if [ ! -e "$src" ]; then 326 atf_fail "file not exist" 327 fi 328 if [ ! -e "$work" ]; then 329 atf_fail "file not exist" 330 fi 331 332 src_checksum=$(md5 -q "$src") 333 work_checksum=$(md5 -q "$work") 334 335 if [ "$work_checksum" != "$src_checksum" ]; then 336 atf_fail "md5 checksum didn't match with ${src} and ${work}" 337 fi 338} 339