1267265Sjilles# 2267265Sjilles# Copyright 2014, Google Inc. All rights reserved. 3267265Sjilles# 4267265Sjilles# Redistribution and use in source and binary forms, with or without 5267265Sjilles# modification, are permitted provided that the following conditions are 6267265Sjilles# met: 7267265Sjilles# 8267265Sjilles# * Redistributions of source code must retain the above copyright 9267265Sjilles# notice, this list of conditions and the following disclaimer. 10267265Sjilles# * Redistributions in binary form must reproduce the above copyright 11267265Sjilles# notice, this list of conditions and the following disclaimer in the 12267265Sjilles# documentation and/or other materials provided with the distribution. 13267265Sjilles# * Neither the name of Google Inc. nor the names of its 14267265Sjilles# contributors may be used to endorse or promote products derived from 15267265Sjilles# this software without specific written permission. 16267265Sjilles# 17267265Sjilles# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18267265Sjilles# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19267265Sjilles# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20267265Sjilles# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21267265Sjilles# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22267265Sjilles# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23267265Sjilles# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24267265Sjilles# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25267265Sjilles# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26267265Sjilles# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27267265Sjilles# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28267265Sjilles# 29267265Sjilles# $FreeBSD$ 30267265Sjilles# 31267265Sjilles 32267265Sjilles# Helper function that is always used to create and fill stderr.txt for these 33267265Sjilles# tests. 34267265Sjilles_custom_create_file() 35267265Sjilles{ 36267265Sjilles # The first argument is a command. 37267265Sjilles # The second is just a string. 38267265Sjilles case "${1}" in 39267265Sjilles creat) > stderr.txt ;; 40267265Sjilles print) [ "${2}" ] && \ 41267265Sjilles printf "%s\n" "${2}" >> stderr.txt ;; 42267265Sjilles esac 43267265Sjilles} 44267265Sjilles 45267265Sjilles# Helper function that create the file stderr.txt that contains the string 46267265Sjilles# passed in as the first argument. 47267265Sjillescreate_stderr_file() 48267265Sjilles{ 49267265Sjilles _custom_create_file creat 50267265Sjilles _custom_create_file print "${1}" 51267265Sjilles} 52267265Sjilles 53267265Sjilles# Helper function that create the file stderr.txt that contains the expected 54267265Sjilles# truncate utility usage message. 55267265Sjillescreate_stderr_usage_file() 56267265Sjilles{ 57267265Sjilles _custom_create_file creat 58267265Sjilles _custom_create_file print "${1}" 59267265Sjilles _custom_create_file print \ 60267265Sjilles "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ..." 61267265Sjilles _custom_create_file print " truncate [-c] -r rfile file ..." 62267265Sjilles} 63267265Sjilles 64267265Sjillesatf_test_case illegal_option 65267265Sjillesillegal_option_head() 66267265Sjilles{ 67267265Sjilles atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 68267265Sjilles "invalid command line option" 69267265Sjilles} 70267265Sjillesillegal_option_body() 71267265Sjilles{ 72267265Sjilles create_stderr_usage_file 'truncate: illegal option -- 7' 73267265Sjilles 74267265Sjilles # We expect the error message, with no new files. 75267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt 76267265Sjilles [ ! -e output.txt ] || atf_fail "output.txt should not exist" 77267265Sjilles} 78267265Sjilles 79267265Sjillesatf_test_case illegal_size 80267265Sjillesillegal_size_head() 81267265Sjilles{ 82267265Sjilles atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 83267265Sjilles "invalid power of two convention" 84267265Sjilles} 85267265Sjillesillegal_size_body() 86267265Sjilles{ 87267265Sjilles create_stderr_file "truncate: invalid size argument \`+1L'" 88267265Sjilles 89267265Sjilles # We expect the error message, with no new files. 90267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt 91267265Sjilles [ ! -e output.txt ] || atf_fail "output.txt should not exist" 92267265Sjilles} 93267265Sjilles 94267265Sjillesatf_test_case too_large_size 95267265Sjillestoo_large_size_head() 96267265Sjilles{ 97267265Sjilles atf_set "descr" "Verifies that truncate exits >0 when passed an" \ 98267265Sjilles "a size that is INT64_MAX < size <= UINT64_MAX" 99267265Sjilles} 100267265Sjillestoo_large_size_body() 101267265Sjilles{ 102267265Sjilles create_stderr_file "truncate: invalid size argument \`8388608t'" 103267265Sjilles 104267265Sjilles # We expect the error message, with no new files. 105267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt \ 106267265Sjilles truncate -s8388608t output.txt 107267265Sjilles [ ! -e output.txt ] || atf_fail "output.txt should not exist" 108267265Sjilles} 109267265Sjilles 110267265Sjillesatf_test_case opt_c 111267265Sjillesopt_c_head() 112267265Sjilles{ 113267265Sjilles atf_set "descr" "Verifies that -c prevents creation of new files" 114267265Sjilles} 115267265Sjillesopt_c_body() 116267265Sjilles{ 117267265Sjilles # No new files and truncate returns 0 as if this is a success. 118267265Sjilles atf_check truncate -c -s 0 doesnotexist.txt 119267265Sjilles [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 120267265Sjilles > reference 121267265Sjilles atf_check truncate -c -r reference doesnotexist.txt 122267265Sjilles [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" 123267265Sjilles 124267265Sjilles create_stderr_file 125267265Sjilles 126267265Sjilles # The existing file will be altered by truncate. 127267265Sjilles > exists.txt 128267265Sjilles atf_check -e file:stderr.txt truncate -c -s1 exists.txt 129267265Sjilles [ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes" 130267265Sjilles} 131267265Sjilles 132267265Sjillesatf_test_case opt_rs 133267265Sjillesopt_rs_head() 134267265Sjilles{ 135267265Sjilles atf_set "descr" "Verifies that truncate command line flags" \ 136267265Sjilles "-s and -r cannot be specifed together" 137267265Sjilles} 138267265Sjillesopt_rs_body() 139267265Sjilles{ 140267265Sjilles create_stderr_usage_file 141267265Sjilles 142267265Sjilles # Force an error due to the use of both -s and -r. 143267265Sjilles > afile 144267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile 145267265Sjilles} 146267265Sjilles 147267265Sjillesatf_test_case no_files 148267265Sjillesno_files_head() 149267265Sjilles{ 150267265Sjilles atf_set "descr" "Verifies that truncate needs a list of files on" \ 151267265Sjilles "the command line" 152267265Sjilles} 153267265Sjillesno_files_body() 154267265Sjilles{ 155267265Sjilles create_stderr_usage_file 156267265Sjilles 157267265Sjilles # A list of files must be present on the command line. 158267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 159267265Sjilles} 160267265Sjilles 161267265Sjillesatf_test_case bad_refer 162267265Sjillesbad_refer_head() 163267265Sjilles{ 164267265Sjilles atf_set "descr" "Verifies that truncate detects a non-existent" \ 165267265Sjilles "reference file" 166267265Sjilles} 167267265Sjillesbad_refer_body() 168267265Sjilles{ 169267265Sjilles create_stderr_file "truncate: afile: No such file or directory" 170267265Sjilles 171267265Sjilles # The reference file must exist before you try to use it. 172267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile 173267265Sjilles [ ! -e afile ] || atf_fail "afile should not exist" 174267265Sjilles} 175267265Sjilles 176294347Sasomersatf_test_case bad_truncate 177267265Sjillesbad_truncate_head() 178267265Sjilles{ 179267265Sjilles atf_set "descr" "Verifies that truncate reports an error during" \ 180267265Sjilles "truncation" 181294347Sasomers atf_set "require.user" "unprivileged" 182267265Sjilles} 183267265Sjillesbad_truncate_body() 184267265Sjilles{ 185294347Sasomers create_stderr_file "truncate: exists.txt: Permission denied" 186267265Sjilles 187267265Sjilles # Trying to get the ftruncate() call to return -1. 188267265Sjilles > exists.txt 189294347Sasomers atf_check chmod 444 exists.txt 190267265Sjilles 191267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt 192267265Sjilles} 193267265Sjilles 194267265Sjillesatf_test_case new_absolute_grow 195267265Sjillesnew_absolute_grow_head() 196267265Sjilles{ 197267265Sjilles atf_set "descr" "Verifies truncate can make and grow a new 1m file" 198267265Sjilles} 199267265Sjillesnew_absolute_grow_body() 200267265Sjilles{ 201267265Sjilles create_stderr_file 202267265Sjilles 203267265Sjilles # Create a new file and grow it to 1024 bytes. 204267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 205267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 206267265Sjilles eval $(stat -s output.txt) 207267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 208267265Sjilles 209267265Sjilles create_stderr_file 210267265Sjilles 211267265Sjilles # Grow the existing file to 1M. We are using absolute sizes. 212267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt 213267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 214267265Sjilles eval $(stat -s output.txt) 215267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 216267265Sjilles} 217267265Sjilles 218267265Sjillesatf_test_case new_absolute_shrink 219267265Sjillesnew_absolute_shrink_head() 220267265Sjilles{ 221267265Sjilles atf_set "descr" "Verifies that truncate can make and" \ 222267265Sjilles "shrink a new 1m file" 223267265Sjilles} 224267265Sjillesnew_absolute_shrink_body() 225267265Sjilles{ 226267265Sjilles create_stderr_file 227267265Sjilles 228267265Sjilles # Create a new file and grow it to 1048576 bytes. 229267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt 230267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 231267265Sjilles eval $(stat -s output.txt) 232267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 233267265Sjilles 234267265Sjilles create_stderr_file 235267265Sjilles 236267265Sjilles # Shrink the existing file to 1k. We are using absolute sizes. 237267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 238267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 239267265Sjilles eval $(stat -s output.txt) 240267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 241267265Sjilles} 242267265Sjilles 243267265Sjillesatf_test_case new_relative_grow 244267265Sjillesnew_relative_grow_head() 245267265Sjilles{ 246267265Sjilles atf_set "descr" "Verifies truncate can make and grow a new 1m file" \ 247267265Sjilles "using relative sizes" 248267265Sjilles} 249267265Sjillesnew_relative_grow_body() 250267265Sjilles{ 251267265Sjilles create_stderr_file 252267265Sjilles 253267265Sjilles # Create a new file and grow it to 1024 bytes. 254267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt 255267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 256267265Sjilles eval $(stat -s output.txt) 257267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 258267265Sjilles 259267265Sjilles create_stderr_file 260267265Sjilles 261267265Sjilles # Grow the existing file to 1M. We are using relative sizes. 262267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt 263267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 264267265Sjilles eval $(stat -s output.txt) 265267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 266267265Sjilles} 267267265Sjilles 268267265Sjillesatf_test_case new_relative_shrink 269267265Sjillesnew_relative_shrink_head() 270267265Sjilles{ 271267265Sjilles atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \ 272267265Sjilles "using relative sizes" 273267265Sjilles} 274267265Sjillesnew_relative_shrink_body() 275267265Sjilles{ 276267265Sjilles create_stderr_file 277267265Sjilles 278267265Sjilles # Create a new file and grow it to 1049600 bytes. 279267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt 280267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 281267265Sjilles eval $(stat -s output.txt) 282267265Sjilles [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m" 283267265Sjilles 284267265Sjilles create_stderr_file 285267265Sjilles 286267265Sjilles # Shrink the existing file to 1k. We are using relative sizes. 287267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt 288267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 289267265Sjilles eval $(stat -s output.txt) 290267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 291267265Sjilles} 292267265Sjilles 293267265Sjillesatf_test_case cannot_open 294267265Sjillescannot_open_head() 295267265Sjilles{ 296267265Sjilles atf_set "descr" "Verifies truncate handles open failures correctly" \ 297267265Sjilles "in a list of files" 298267265Sjilles atf_set "require.user" "unprivileged" 299267265Sjilles} 300267265Sjillescannot_open_body() 301267265Sjilles{ 302267265Sjilles # Create three files -- the middle file cannot allow writes. 303267265Sjilles > before 304267265Sjilles > 0000 305267265Sjilles > after 306267265Sjilles atf_check chmod 0000 0000 307267265Sjilles 308267265Sjilles create_stderr_file "truncate: 0000: Permission denied" 309267265Sjilles 310267265Sjilles # Create a new file and grow it to 1024 bytes. 311267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt \ 312267265Sjilles truncate -c -s1k before 0000 after 313267265Sjilles eval $(stat -s before) 314267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 315267265Sjilles eval $(stat -s after) 316267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 317267265Sjilles eval $(stat -s 0000) 318267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 319267265Sjilles} 320267265Sjilles 321267265Sjillesatf_test_case reference 322267265Sjillesreference_head() 323267265Sjilles{ 324267265Sjilles atf_set "descr" "Verifies that truncate can use a reference file" 325267265Sjilles} 326267265Sjillesreference_body() 327267265Sjilles{ 328267265Sjilles # Create a 4 byte reference file. 329267265Sjilles printf "123\n" > reference 330267265Sjilles eval $(stat -s reference) 331267265Sjilles [ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes" 332267265Sjilles 333267265Sjilles create_stderr_file 334267265Sjilles 335267265Sjilles # Create a new file and grow it to 4 bytes. 336267265Sjilles atf_check -e file:stderr.txt truncate -r reference afile 337267265Sjilles eval $(stat -s afile) 338267265Sjilles [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes" 339267265Sjilles} 340267265Sjilles 341267265Sjillesatf_test_case new_zero 342267265Sjillesnew_zero_head() 343267265Sjilles{ 344267265Sjilles atf_set "descr" "Verifies truncate can make and grow zero byte file" 345267265Sjilles} 346267265Sjillesnew_zero_body() 347267265Sjilles{ 348267265Sjilles create_stderr_file 349267265Sjilles 350267265Sjilles # Create a new file and grow it to zero bytes. 351267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt 352267265Sjilles eval $(stat -s output.txt) 353267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 354267265Sjilles 355267265Sjilles # Pretend to grow the file. 356267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt 357267265Sjilles eval $(stat -s output.txt) 358267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 359267265Sjilles} 360267265Sjilles 361267265Sjillesatf_test_case negative 362267265Sjillesnegative_head() 363267265Sjilles{ 364267265Sjilles atf_set "descr" "Verifies truncate treats negative sizes as zero" 365267265Sjilles} 366267265Sjillesnegative_body() 367267265Sjilles{ 368267265Sjilles # Create a 5 byte file. 369267265Sjilles printf "abcd\n" > afile 370267265Sjilles eval $(stat -s afile) 371267265Sjilles [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 372267265Sjilles 373267265Sjilles create_stderr_file 374267265Sjilles 375267265Sjilles # Create a new file and do a 100 byte negative relative shrink. 376267265Sjilles atf_check -e file:stderr.txt truncate -s-100 afile 377267265Sjilles eval $(stat -s afile) 378267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes" 379267265Sjilles} 380267265Sjilles 381267265Sjillesatf_init_test_cases() 382267265Sjilles{ 383267265Sjilles atf_add_test_case illegal_option 384267265Sjilles atf_add_test_case illegal_size 385267265Sjilles atf_add_test_case too_large_size 386267265Sjilles atf_add_test_case opt_c 387267265Sjilles atf_add_test_case opt_rs 388267265Sjilles atf_add_test_case no_files 389267265Sjilles atf_add_test_case bad_refer 390267265Sjilles atf_add_test_case bad_truncate 391267265Sjilles atf_add_test_case cannot_open 392267265Sjilles atf_add_test_case new_absolute_grow 393267265Sjilles atf_add_test_case new_absolute_shrink 394267265Sjilles atf_add_test_case new_relative_grow 395267265Sjilles atf_add_test_case new_relative_shrink 396267265Sjilles atf_add_test_case reference 397267265Sjilles atf_add_test_case new_zero 398267265Sjilles atf_add_test_case negative 399267265Sjilles} 400