1# 2# Copyright 2014, Google Inc. All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: 7# 8# * Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# * Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# * Neither the name of Google Inc. nor the names of its 14# contributors may be used to endorse or promote products derived from 15# this software without specific written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28# 29# $FreeBSD$ 30# 31 32# Helper function that is always used to create and fill stderr.txt for these 33# tests. 34_custom_create_file() 35{ 36 # The first argument is a command. 37 # The second is just a string. 38 case "${1}" in 39 creat) > stderr.txt ;; 40 print) [ "${2}" ] && \ 41 printf "%s\n" "${2}" >> stderr.txt ;; 42 esac 43} 44 45# Helper function that create the file stderr.txt that contains the string 46# passed in as the first argument. 47create_stderr_file() 48{ 49 _custom_create_file creat 50 _custom_create_file print "${1}" 51} 52 53# Helper function that create the file stderr.txt that contains the expected 54# truncate utility usage message. 55create_stderr_usage_file() 56{ 57 _custom_create_file creat 58 _custom_create_file print "${1}" 59 _custom_create_file print \ 60 "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ..." 61 _custom_create_file print " truncate [-c] -r rfile file ..." 62 _custom_create_file print " truncate [-c] -d [-o offset[K|k|M|m|G|g|T|t]] -l length[K|k|M|m|G|g|T|t] file ..." 63} 64 65atf_test_case illegal_option 66illegal_option_head() 67{ 68 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 69 "invalid command line option" 70} 71illegal_option_body() 72{ 73 create_stderr_usage_file 'truncate: illegal option -- 7' 74 75 # We expect the error message, with no new files. 76 atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt 77 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 78} 79 80atf_test_case illegal_size 81illegal_size_head() 82{ 83 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 84 "invalid power of two convention" 85} 86illegal_size_body() 87{ 88 create_stderr_file "truncate: invalid size argument \`+1L'" 89 90 # We expect the error message, with no new files. 91 atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt 92 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 93} 94 95atf_test_case too_large_size 96too_large_size_head() 97{ 98 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 99 "a size that is INT64_MAX < size <= UINT64_MAX" 100} 101too_large_size_body() 102{ 103 create_stderr_file "truncate: invalid size argument \`8388608t'" 104 105 # We expect the error message, with no new files. 106 atf_check -s not-exit:0 -e file:stderr.txt \ 107 truncate -s8388608t output.txt 108 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 109} 110 111atf_test_case opt_c 112opt_c_head() 113{ 114 atf_set "descr" "Verifies that -c prevents creation of new files" 115} 116opt_c_body() 117{ 118 # No new files and truncate returns 0 as if this is a success. 119 atf_check truncate -c -s 0 doesnotexist.txt 120 [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 121 > reference 122 atf_check truncate -c -r reference doesnotexist.txt 123 [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 124 125 create_stderr_file 126 127 # The existing file will be altered by truncate. 128 > exists.txt 129 atf_check -e file:stderr.txt truncate -c -s1 exists.txt 130 [ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes" 131} 132 133atf_test_case opt_rs 134opt_rs_head() 135{ 136 atf_set "descr" "Verifies that truncate command line flags" \ 137 "-s and -r cannot be specifed together" 138} 139opt_rs_body() 140{ 141 create_stderr_usage_file 142 143 # Force an error due to the use of both -s and -r. 144 > afile 145 atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile 146} 147 148atf_test_case no_files 149no_files_head() 150{ 151 atf_set "descr" "Verifies that truncate needs a list of files on" \ 152 "the command line" 153} 154no_files_body() 155{ 156 create_stderr_usage_file 157 158 # A list of files must be present on the command line. 159 atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 160} 161 162atf_test_case bad_refer 163bad_refer_head() 164{ 165 atf_set "descr" "Verifies that truncate detects a non-existent" \ 166 "reference file" 167} 168bad_refer_body() 169{ 170 create_stderr_file "truncate: afile: No such file or directory" 171 172 # The reference file must exist before you try to use it. 173 atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile 174 [ ! -e afile ] || atf_fail "afile should not exist" 175} 176 177atf_test_case bad_truncate 178bad_truncate_head() 179{ 180 atf_set "descr" "Verifies that truncate reports an error during" \ 181 "truncation" 182 atf_set "require.user" "unprivileged" 183} 184bad_truncate_body() 185{ 186 create_stderr_file "truncate: exists.txt: Permission denied" 187 188 # Trying to get the ftruncate() call to return -1. 189 > exists.txt 190 atf_check chmod 444 exists.txt 191 192 atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt 193} 194 195atf_test_case new_absolute_grow 196new_absolute_grow_head() 197{ 198 atf_set "descr" "Verifies truncate can make and grow a new 1m file" 199} 200new_absolute_grow_body() 201{ 202 create_stderr_file 203 204 # Create a new file and grow it to 1024 bytes. 205 atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 206 atf_check -s exit:1 cmp -s output.txt /dev/zero 207 eval $(stat -s output.txt) 208 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 209 210 create_stderr_file 211 212 # Grow the existing file to 1M. We are using absolute sizes. 213 atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt 214 atf_check -s exit:1 cmp -s output.txt /dev/zero 215 eval $(stat -s output.txt) 216 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 217} 218 219atf_test_case new_absolute_shrink 220new_absolute_shrink_head() 221{ 222 atf_set "descr" "Verifies that truncate can make and" \ 223 "shrink a new 1m file" 224} 225new_absolute_shrink_body() 226{ 227 create_stderr_file 228 229 # Create a new file and grow it to 1048576 bytes. 230 atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt 231 atf_check -s exit:1 cmp -s output.txt /dev/zero 232 eval $(stat -s output.txt) 233 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 234 235 create_stderr_file 236 237 # Shrink the existing file to 1k. We are using absolute sizes. 238 atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 239 atf_check -s exit:1 cmp -s output.txt /dev/zero 240 eval $(stat -s output.txt) 241 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 242} 243 244atf_test_case new_relative_grow 245new_relative_grow_head() 246{ 247 atf_set "descr" "Verifies truncate can make and grow a new 1m file" \ 248 "using relative sizes" 249} 250new_relative_grow_body() 251{ 252 create_stderr_file 253 254 # Create a new file and grow it to 1024 bytes. 255 atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt 256 atf_check -s exit:1 cmp -s output.txt /dev/zero 257 eval $(stat -s output.txt) 258 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 259 260 create_stderr_file 261 262 # Grow the existing file to 1M. We are using relative sizes. 263 atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt 264 atf_check -s exit:1 cmp -s output.txt /dev/zero 265 eval $(stat -s output.txt) 266 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 267} 268 269atf_test_case new_relative_shrink 270new_relative_shrink_head() 271{ 272 atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \ 273 "using relative sizes" 274} 275new_relative_shrink_body() 276{ 277 create_stderr_file 278 279 # Create a new file and grow it to 1049600 bytes. 280 atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt 281 atf_check -s exit:1 cmp -s output.txt /dev/zero 282 eval $(stat -s output.txt) 283 [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m" 284 285 create_stderr_file 286 287 # Shrink the existing file to 1k. We are using relative sizes. 288 atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt 289 atf_check -s exit:1 cmp -s output.txt /dev/zero 290 eval $(stat -s output.txt) 291 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 292} 293 294atf_test_case cannot_open 295cannot_open_head() 296{ 297 atf_set "descr" "Verifies truncate handles open failures correctly" \ 298 "in a list of files" 299 atf_set "require.user" "unprivileged" 300} 301cannot_open_body() 302{ 303 # Create three files -- the middle file cannot allow writes. 304 > before 305 > 0000 306 > after 307 atf_check chmod 0000 0000 308 309 create_stderr_file "truncate: 0000: Permission denied" 310 311 # Create a new file and grow it to 1024 bytes. 312 atf_check -s not-exit:0 -e file:stderr.txt \ 313 truncate -c -s1k before 0000 after 314 eval $(stat -s before) 315 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 316 eval $(stat -s after) 317 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 318 eval $(stat -s 0000) 319 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 320} 321 322atf_test_case reference 323reference_head() 324{ 325 atf_set "descr" "Verifies that truncate can use a reference file" 326} 327reference_body() 328{ 329 # Create a 4 byte reference file. 330 printf "123\n" > reference 331 eval $(stat -s reference) 332 [ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes" 333 334 create_stderr_file 335 336 # Create a new file and grow it to 4 bytes. 337 atf_check -e file:stderr.txt truncate -r reference afile 338 eval $(stat -s afile) 339 [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes" 340} 341 342atf_test_case new_zero 343new_zero_head() 344{ 345 atf_set "descr" "Verifies truncate can make and grow zero byte file" 346} 347new_zero_body() 348{ 349 create_stderr_file 350 351 # Create a new file and grow it to zero bytes. 352 atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt 353 eval $(stat -s output.txt) 354 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 355 356 # Pretend to grow the file. 357 atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt 358 eval $(stat -s output.txt) 359 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 360} 361 362atf_test_case negative 363negative_head() 364{ 365 atf_set "descr" "Verifies truncate treats negative sizes as zero" 366} 367negative_body() 368{ 369 # Create a 5 byte file. 370 printf "abcd\n" > afile 371 eval $(stat -s afile) 372 [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 373 374 create_stderr_file 375 376 # Create a new file and do a 100 byte negative relative shrink. 377 atf_check -e file:stderr.txt truncate -s-100 afile 378 eval $(stat -s afile) 379 [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes" 380} 381 382atf_test_case roundup 383roundup_head() 384{ 385 atf_set "descr" "Verifies truncate round up" 386} 387roundup_body() 388{ 389 # Create a 5 byte file. 390 printf "abcd\n" > afile 391 eval $(stat -s afile) 392 [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 393 394 create_stderr_file 395 396 # Create a new file and do a 100 byte roundup. 397 atf_check -e file:stderr.txt truncate -s%100 afile 398 eval $(stat -s afile) 399 [ ${st_size} -eq 100 ] || atf_fail "new file should now be 100 bytes" 400} 401 402atf_test_case rounddown 403rounddown_head() 404{ 405 atf_set "descr" "Verifies truncate round down" 406} 407rounddown_body() 408{ 409 # Create a 5 byte file. 410 printf "abcd\n" > afile 411 eval $(stat -s afile) 412 [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 413 414 create_stderr_file 415 416 # Create a new file and do a 2 byte roundup. 417 atf_check -e file:stderr.txt truncate -s/2 afile 418 eval $(stat -s afile) 419 [ ${st_size} -eq 4 ] || atf_fail "new file should now be 4 bytes" 420} 421 422atf_test_case rounddown_zero 423rounddown_zero_head() 424{ 425 atf_set "descr" "Verifies truncate round down to zero" 426} 427rounddown_zero_body() 428{ 429 # Create a 5 byte file. 430 printf "abcd\n" > afile 431 eval $(stat -s afile) 432 [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 433 434 create_stderr_file 435 436 # Create a new file and do a 10 byte roundup. 437 atf_check -e file:stderr.txt truncate -s/10 afile 438 eval $(stat -s afile) 439 [ ${st_size} -eq 0 ] || atf_fail "new file should now be 0 bytes" 440} 441 442atf_init_test_cases() 443{ 444 atf_add_test_case illegal_option 445 atf_add_test_case illegal_size 446 atf_add_test_case too_large_size 447 atf_add_test_case opt_c 448 atf_add_test_case opt_rs 449 atf_add_test_case no_files 450 atf_add_test_case bad_refer 451 atf_add_test_case bad_truncate 452 atf_add_test_case cannot_open 453 atf_add_test_case new_absolute_grow 454 atf_add_test_case new_absolute_shrink 455 atf_add_test_case new_relative_grow 456 atf_add_test_case new_relative_shrink 457 atf_add_test_case reference 458 atf_add_test_case new_zero 459 atf_add_test_case negative 460 atf_add_test_case roundup 461 atf_add_test_case rounddown 462 atf_add_test_case rounddown_zero 463} 464