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: releng/10.2/usr.bin/truncate/tests/truncate_test.sh 267265 2014-06-09 10:39:55Z jilles $ 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 176267265Sjillesatf_test_case bad_truncate cleanup 177267265Sjillesbad_truncate_head() 178267265Sjilles{ 179267265Sjilles atf_set "descr" "Verifies that truncate reports an error during" \ 180267265Sjilles "truncation" 181267265Sjilles} 182267265Sjillesbad_truncate_body() 183267265Sjilles{ 184267265Sjilles create_stderr_file "truncate: exists.txt: Operation not permitted" 185267265Sjilles 186267265Sjilles # Trying to get the ftruncate() call to return -1. 187267265Sjilles > exists.txt 188267265Sjilles atf_check chflags uimmutable exists.txt 189267265Sjilles 190267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt 191267265Sjilles} 192267265Sjillesbad_truncate_cleanup() 193267265Sjilles{ 194267265Sjilles chflags 0 exists.txt 195267265Sjilles} 196267265Sjilles 197267265Sjillesatf_test_case new_absolute_grow 198267265Sjillesnew_absolute_grow_head() 199267265Sjilles{ 200267265Sjilles atf_set "descr" "Verifies truncate can make and grow a new 1m file" 201267265Sjilles} 202267265Sjillesnew_absolute_grow_body() 203267265Sjilles{ 204267265Sjilles create_stderr_file 205267265Sjilles 206267265Sjilles # Create a new file and grow it to 1024 bytes. 207267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 208267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 209267265Sjilles eval $(stat -s output.txt) 210267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 211267265Sjilles 212267265Sjilles create_stderr_file 213267265Sjilles 214267265Sjilles # Grow the existing file to 1M. We are using absolute sizes. 215267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt 216267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 217267265Sjilles eval $(stat -s output.txt) 218267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 219267265Sjilles} 220267265Sjilles 221267265Sjillesatf_test_case new_absolute_shrink 222267265Sjillesnew_absolute_shrink_head() 223267265Sjilles{ 224267265Sjilles atf_set "descr" "Verifies that truncate can make and" \ 225267265Sjilles "shrink a new 1m file" 226267265Sjilles} 227267265Sjillesnew_absolute_shrink_body() 228267265Sjilles{ 229267265Sjilles create_stderr_file 230267265Sjilles 231267265Sjilles # Create a new file and grow it to 1048576 bytes. 232267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt 233267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 234267265Sjilles eval $(stat -s output.txt) 235267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 236267265Sjilles 237267265Sjilles create_stderr_file 238267265Sjilles 239267265Sjilles # Shrink the existing file to 1k. We are using absolute sizes. 240267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt 241267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 242267265Sjilles eval $(stat -s output.txt) 243267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 244267265Sjilles} 245267265Sjilles 246267265Sjillesatf_test_case new_relative_grow 247267265Sjillesnew_relative_grow_head() 248267265Sjilles{ 249267265Sjilles atf_set "descr" "Verifies truncate can make and grow a new 1m file" \ 250267265Sjilles "using relative sizes" 251267265Sjilles} 252267265Sjillesnew_relative_grow_body() 253267265Sjilles{ 254267265Sjilles create_stderr_file 255267265Sjilles 256267265Sjilles # Create a new file and grow it to 1024 bytes. 257267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt 258267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 259267265Sjilles eval $(stat -s output.txt) 260267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 261267265Sjilles 262267265Sjilles create_stderr_file 263267265Sjilles 264267265Sjilles # Grow the existing file to 1M. We are using relative sizes. 265267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt 266267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 267267265Sjilles eval $(stat -s output.txt) 268267265Sjilles [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" 269267265Sjilles} 270267265Sjilles 271267265Sjillesatf_test_case new_relative_shrink 272267265Sjillesnew_relative_shrink_head() 273267265Sjilles{ 274267265Sjilles atf_set "descr" "Verifies truncate can make and shrink a new 1m file" \ 275267265Sjilles "using relative sizes" 276267265Sjilles} 277267265Sjillesnew_relative_shrink_body() 278267265Sjilles{ 279267265Sjilles create_stderr_file 280267265Sjilles 281267265Sjilles # Create a new file and grow it to 1049600 bytes. 282267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt 283267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 284267265Sjilles eval $(stat -s output.txt) 285267265Sjilles [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m" 286267265Sjilles 287267265Sjilles create_stderr_file 288267265Sjilles 289267265Sjilles # Shrink the existing file to 1k. We are using relative sizes. 290267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt 291267265Sjilles atf_check -s exit:1 cmp -s output.txt /dev/zero 292267265Sjilles eval $(stat -s output.txt) 293267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 294267265Sjilles} 295267265Sjilles 296267265Sjillesatf_test_case cannot_open 297267265Sjillescannot_open_head() 298267265Sjilles{ 299267265Sjilles atf_set "descr" "Verifies truncate handles open failures correctly" \ 300267265Sjilles "in a list of files" 301267265Sjilles atf_set "require.user" "unprivileged" 302267265Sjilles} 303267265Sjillescannot_open_body() 304267265Sjilles{ 305267265Sjilles # Create three files -- the middle file cannot allow writes. 306267265Sjilles > before 307267265Sjilles > 0000 308267265Sjilles > after 309267265Sjilles atf_check chmod 0000 0000 310267265Sjilles 311267265Sjilles create_stderr_file "truncate: 0000: Permission denied" 312267265Sjilles 313267265Sjilles # Create a new file and grow it to 1024 bytes. 314267265Sjilles atf_check -s not-exit:0 -e file:stderr.txt \ 315267265Sjilles truncate -c -s1k before 0000 after 316267265Sjilles eval $(stat -s before) 317267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 318267265Sjilles eval $(stat -s after) 319267265Sjilles [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" 320267265Sjilles eval $(stat -s 0000) 321267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 322267265Sjilles} 323267265Sjilles 324267265Sjillesatf_test_case reference 325267265Sjillesreference_head() 326267265Sjilles{ 327267265Sjilles atf_set "descr" "Verifies that truncate can use a reference file" 328267265Sjilles} 329267265Sjillesreference_body() 330267265Sjilles{ 331267265Sjilles # Create a 4 byte reference file. 332267265Sjilles printf "123\n" > reference 333267265Sjilles eval $(stat -s reference) 334267265Sjilles [ ${st_size} -eq 4 ] || atf_fail "reference file should be 4 bytes" 335267265Sjilles 336267265Sjilles create_stderr_file 337267265Sjilles 338267265Sjilles # Create a new file and grow it to 4 bytes. 339267265Sjilles atf_check -e file:stderr.txt truncate -r reference afile 340267265Sjilles eval $(stat -s afile) 341267265Sjilles [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes" 342267265Sjilles} 343267265Sjilles 344267265Sjillesatf_test_case new_zero 345267265Sjillesnew_zero_head() 346267265Sjilles{ 347267265Sjilles atf_set "descr" "Verifies truncate can make and grow zero byte file" 348267265Sjilles} 349267265Sjillesnew_zero_body() 350267265Sjilles{ 351267265Sjilles create_stderr_file 352267265Sjilles 353267265Sjilles # Create a new file and grow it to zero bytes. 354267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt 355267265Sjilles eval $(stat -s output.txt) 356267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 357267265Sjilles 358267265Sjilles # Pretend to grow the file. 359267265Sjilles atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt 360267265Sjilles eval $(stat -s output.txt) 361267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" 362267265Sjilles} 363267265Sjilles 364267265Sjillesatf_test_case negative 365267265Sjillesnegative_head() 366267265Sjilles{ 367267265Sjilles atf_set "descr" "Verifies truncate treats negative sizes as zero" 368267265Sjilles} 369267265Sjillesnegative_body() 370267265Sjilles{ 371267265Sjilles # Create a 5 byte file. 372267265Sjilles printf "abcd\n" > afile 373267265Sjilles eval $(stat -s afile) 374267265Sjilles [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes" 375267265Sjilles 376267265Sjilles create_stderr_file 377267265Sjilles 378267265Sjilles # Create a new file and do a 100 byte negative relative shrink. 379267265Sjilles atf_check -e file:stderr.txt truncate -s-100 afile 380267265Sjilles eval $(stat -s afile) 381267265Sjilles [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes" 382267265Sjilles} 383267265Sjilles 384267265Sjillesatf_init_test_cases() 385267265Sjilles{ 386267265Sjilles atf_add_test_case illegal_option 387267265Sjilles atf_add_test_case illegal_size 388267265Sjilles atf_add_test_case too_large_size 389267265Sjilles atf_add_test_case opt_c 390267265Sjilles atf_add_test_case opt_rs 391267265Sjilles atf_add_test_case no_files 392267265Sjilles atf_add_test_case bad_refer 393267265Sjilles atf_add_test_case bad_truncate 394267265Sjilles atf_add_test_case cannot_open 395267265Sjilles atf_add_test_case new_absolute_grow 396267265Sjilles atf_add_test_case new_absolute_shrink 397267265Sjilles atf_add_test_case new_relative_grow 398267265Sjilles atf_add_test_case new_relative_shrink 399267265Sjilles atf_add_test_case reference 400267265Sjilles atf_add_test_case new_zero 401267265Sjilles atf_add_test_case negative 402267265Sjilles} 403