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} 63 64atf_test_case illegal_option 65illegal_option_head() 66{ 67 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 68 "invalid command line option" 69} 70illegal_option_body() 71{ 72 create_stderr_usage_file 'truncate: illegal option -- 7' 73 74 # We expect the error message, with no new files. 75 atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt 76 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 77} 78 79atf_test_case illegal_size 80illegal_size_head() 81{ 82 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 83 "invalid power of two convention" 84} 85illegal_size_body() 86{ 87 create_stderr_file "truncate: invalid size argument \`+1L'" 88 89 # We expect the error message, with no new files. 90 atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt 91 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 92} 93 94atf_test_case too_large_size 95too_large_size_head() 96{ 97 atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 98 "a size that is INT64_MAX < size <= UINT64_MAX" 99} 100too_large_size_body() 101{ 102 create_stderr_file "truncate: invalid size argument \`8388608t'" 103 104 # We expect the error message, with no new files. 105 atf_check -s not-exit:0 -e file:stderr.txt \ 106 truncate -s8388608t output.txt 107 [ ! -e output.txt ] || atf_fail "output.txt should not exist" 108} 109 110atf_test_case opt_c 111opt_c_head() 112{ 113 atf_set "descr" "Verifies that -c prevents creation of new files" 114} 115opt_c_body() 116{ 117 # No new files and truncate returns 0 as if this is a success. 118 atf_check truncate -c -s 0 doesnotexist.txt 119 [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 120 > reference 121 atf_check truncate -c -r reference doesnotexist.txt 122 [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 123 124 create_stderr_file 125 126 # The existing file will be altered by truncate. 127 > exists.txt 128 atf_check -e file:stderr.txt truncate -c -s1 exists.txt 129 [ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes" 130} 131 132atf_test_case opt_rs 133opt_rs_head() 134{ 135 atf_set "descr" "Verifies that truncate command line flags" \ 136 "-s and -r cannot be specifed together" 137} 138opt_rs_body() 139{ 140 create_stderr_usage_file 141 142 # Force an error due to the use of both -s and -r. 143 > afile 144 atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile 145} 146 147atf_test_case no_files 148no_files_head() 149{ 150 atf_set "descr" "Verifies that truncate needs a list of files on" \ 151 "the command line" 152} 153no_files_body() 154{ 155 create_stderr_usage_file 156 157 # A list of files must be present on the command line. 158 atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 159} 160 161atf_test_case bad_refer 162bad_refer_head() 163{ 164 atf_set "descr" "Verifies that truncate detects a non-existent" \ 165 "reference file" 166} 167bad_refer_body() 168{ 169 create_stderr_file "truncate: afile: No such file or directory" 170 171 # The reference file must exist before you try to use it. 172 atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile 173 [ ! -e afile ] || atf_fail "afile should not exist" 174} 175 176atf_test_case bad_truncate cleanup 177bad_truncate_head() 178{ 179 atf_set "descr" "Verifies that truncate reports an error during" \ 180 "truncation" 181} 182bad_truncate_body() 183{ 184 create_stderr_file "truncate: exists.txt: Operation not permitted" 185 186 # Trying to get the ftruncate() call to return -1. 187 > exists.txt 188 atf_check chflags uimmutable exists.txt 189 190 atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt 191} 192bad_truncate_cleanup() 193{ 194 chflags 0 exists.txt 195} 196 197atf_test_case new_absolute_grow 198new_absolute_grow_head() 199{ 200 atf_set "descr" "Verifies truncate can make and grow a new 1m file" 201} 202new_absolute_grow_body() 203{ 204 create_stderr_file 205 206 # Create a new file and grow it to 1024 bytes. 207 atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 208 atf_check -s exit:1 cmp -s output.txt /dev/zero 209 eval $(stat -s output.txt) 210 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 211 212 create_stderr_file 213 214 # Grow the existing file to 1M. We are using absolute sizes. 215 atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt 216 atf_check -s exit:1 cmp -s output.txt /dev/zero 217 eval $(stat -s output.txt) 218 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 219} 220 221atf_test_case new_absolute_shrink 222new_absolute_shrink_head() 223{ 224 atf_set "descr" "Verifies that truncate can make and" \ 225 "shrink a new 1m file" 226} 227new_absolute_shrink_body() 228{ 229 create_stderr_file 230 231 # Create a new file and grow it to 1048576 bytes. 232 atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt 233 atf_check -s exit:1 cmp -s output.txt /dev/zero 234 eval $(stat -s output.txt) 235 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 236 237 create_stderr_file 238 239 # Shrink the existing file to 1k. We are using absolute sizes. 240 atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 241 atf_check -s exit:1 cmp -s output.txt /dev/zero 242 eval $(stat -s output.txt) 243 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 244} 245 246atf_test_case new_relative_grow 247new_relative_grow_head() 248{ 249 atf_set "descr" "Verifies truncate can make and grow a new 1m file" \ 250 "using relative sizes" 251} 252new_relative_grow_body() 253{ 254 create_stderr_file 255 256 # Create a new file and grow it to 1024 bytes. 257 atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt 258 atf_check -s exit:1 cmp -s output.txt /dev/zero 259 eval $(stat -s output.txt) 260 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 261 262 create_stderr_file 263 264 # Grow the existing file to 1M. We are using relative sizes. 265 atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt 266 atf_check -s exit:1 cmp -s output.txt /dev/zero 267 eval $(stat -s output.txt) 268 [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 269} 270 271atf_test_case new_relative_shrink 272new_relative_shrink_head() 273{ 274 atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \ 275 "using relative sizes" 276} 277new_relative_shrink_body() 278{ 279 create_stderr_file 280 281 # Create a new file and grow it to 1049600 bytes. 282 atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt 283 atf_check -s exit:1 cmp -s output.txt /dev/zero 284 eval $(stat -s output.txt) 285 [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m" 286 287 create_stderr_file 288 289 # Shrink the existing file to 1k. We are using relative sizes. 290 atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt 291 atf_check -s exit:1 cmp -s output.txt /dev/zero 292 eval $(stat -s output.txt) 293 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 294} 295 296atf_test_case cannot_open 297cannot_open_head() 298{ 299 atf_set "descr" "Verifies truncate handles open failures correctly" \ 300 "in a list of files" 301 atf_set "require.user" "unprivileged" 302} 303cannot_open_body() 304{ 305 # Create three files -- the middle file cannot allow writes. 306 > before 307 > 0000 308 > after 309 atf_check chmod 0000 0000 310 311 create_stderr_file "truncate: 0000: Permission denied" 312 313 # Create a new file and grow it to 1024 bytes. 314 atf_check -s not-exit:0 -e file:stderr.txt \ 315 truncate -c -s1k before 0000 after 316 eval $(stat -s before) 317 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 318 eval $(stat -s after) 319 [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 320 eval $(stat -s 0000) 321 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 322} 323 324atf_test_case reference 325reference_head() 326{ 327 atf_set "descr" "Verifies that truncate can use a reference file" 328} 329reference_body() 330{ 331 # Create a 4 byte reference file. 332 printf "123\n" > reference 333 eval $(stat -s reference) 334 [ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes" 335 336 create_stderr_file 337 338 # Create a new file and grow it to 4 bytes. 339 atf_check -e file:stderr.txt truncate -r reference afile 340 eval $(stat -s afile) 341 [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes" 342} 343 344atf_test_case new_zero 345new_zero_head() 346{ 347 atf_set "descr" "Verifies truncate can make and grow zero byte file" 348} 349new_zero_body() 350{ 351 create_stderr_file 352 353 # Create a new file and grow it to zero bytes. 354 atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt 355 eval $(stat -s output.txt) 356 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 357 358 # Pretend to grow the file. 359 atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt 360 eval $(stat -s output.txt) 361 [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 362} 363 364atf_test_case negative 365negative_head() 366{ 367 atf_set "descr" "Verifies truncate treats negative sizes as zero" 368} 369negative_body() 370{ 371 # Create a 5 byte file. 372 printf "abcd\n" > afile 373 eval $(stat -s afile) 374 [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 375 376 create_stderr_file 377 378 # Create a new file and do a 100 byte negative relative shrink. 379 atf_check -e file:stderr.txt truncate -s-100 afile 380 eval $(stat -s afile) 381 [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes" 382} 383 384atf_init_test_cases() 385{ 386 atf_add_test_case illegal_option 387 atf_add_test_case illegal_size 388 atf_add_test_case too_large_size 389 atf_add_test_case opt_c 390 atf_add_test_case opt_rs 391 atf_add_test_case no_files 392 atf_add_test_case bad_refer 393 atf_add_test_case bad_truncate 394 atf_add_test_case cannot_open 395 atf_add_test_case new_absolute_grow 396 atf_add_test_case new_absolute_shrink 397 atf_add_test_case new_relative_grow 398 atf_add_test_case new_relative_shrink 399 atf_add_test_case reference 400 atf_add_test_case new_zero 401 atf_add_test_case negative 402} 403