1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2016 Alan Somers 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. 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# 14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24# SUCH DAMAGE. 25# 26 27atf_test_case empty_r 28empty_r_head() 29{ 30 atf_set "descr" "Reverse an empty file" 31} 32empty_r_body() 33{ 34 touch infile expectfile 35 tail -r infile > outfile 36 tail -r < infile > outpipe 37 atf_check cmp expectfile outfile 38 atf_check cmp expectfile outpipe 39} 40 41atf_test_case file_r 42file_r_head() 43{ 44 atf_set "descr" "Reverse a file" 45} 46file_r_body() 47{ 48 cat > infile <<HERE 49This is the first line 50This is the second line 51This is the third line 52HERE 53 cat > expectfile << HERE 54This is the third line 55This is the second line 56This is the first line 57HERE 58 tail -r infile > outfile 59 tail -r < infile > outpipe 60 atf_check cmp expectfile outfile 61 atf_check cmp expectfile outpipe 62} 63 64atf_test_case file_rn2 65file_rn2_head() 66{ 67 atf_set "descr" "Reverse the last two lines of a file" 68} 69file_rn2_body() 70{ 71 cat > infile <<HERE 72This is the first line 73This is the second line 74This is the third line 75HERE 76 cat > expectfile << HERE 77This is the third line 78This is the second line 79HERE 80 tail -rn2 infile > outfile 81 tail -rn2 < infile > outpipe 82 atf_check cmp expectfile outfile 83 atf_check cmp expectfile outpipe 84} 85 86# Regression test for PR 222671 87# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222671 88atf_test_case pipe_leading_newline_r 89pipe_leading_newline_r_head() 90{ 91 atf_set "descr" "Reverse a pipe whose first character is a newline" 92} 93pipe_leading_newline_r_body() 94{ 95 cat > expectfile << HERE 963 972 981 99 100HERE 101 printf '\n1\n2\n3\n' | tail -r > outfile 102 printf '\n1\n2\n3\n' | tail -r > outpipe 103 atf_check cmp expectfile outfile 104 atf_check cmp expectfile outpipe 105} 106 107atf_test_case file_rc28 108file_rc28_head() 109{ 110 atf_set "descr" "Reverse a file and display the last 28 characters" 111} 112file_rc28_body() 113{ 114 cat > infile <<HERE 115This is the first line 116This is the second line 117This is the third line 118HERE 119 cat > expectfile << HERE 120This is the third line 121line 122HERE 123 tail -rc28 infile > outfile 124 tail -rc28 < infile > outpipe 125 atf_check cmp expectfile outfile 126 atf_check cmp expectfile outpipe 127} 128 129atf_test_case file_rc28 130file_rc28_head() 131{ 132 atf_set "descr" "Reverse a file and display the last 28 characters" 133} 134file_rc28_body() 135{ 136 cat > infile <<HERE 137This is the first line 138This is the second line 139This is the third line 140HERE 141 cat > expectfile << HERE 142This is the third line 143line 144HERE 145 tail -rc28 infile > outfile 146 tail -rc28 < infile > outpipe 147 atf_check cmp expectfile outfile 148 atf_check cmp expectfile outpipe 149} 150 151atf_test_case longfile_r 152longfile_r_head() 153{ 154 atf_set "descr" "Reverse a long file" 155} 156longfile_r_body() 157{ 158 jot -w "%0511d" 1030 0 > infile 159 jot -w "%0511d" 1030 1029 0 -1 > expectfile 160 tail -r infile > outfile 161 tail -r < infile > outpipe 162 atf_check cmp expectfile outfile 163 atf_check cmp expectfile outpipe 164} 165 166atf_test_case longfile_r_enomem 167longfile_r_enomem_head() 168{ 169 atf_set "descr" "Reverse a file that's too long to store in RAM" 170} 171longfile_r_enomem_body() 172{ 173 # When we reverse a file that's too long for RAM, tail should drop the 174 # first part and just print what it can. We'll check that the last 175 # part is ok 176 { 177 ulimit -v 32768 || atf_skip "Can't adjust ulimit" 178 jot -w "%01023d" 32768 0 | tail -r > outfile ; 179 } 180 if [ "$?" -ne 1 ]; then 181 atf_skip "Didn't get ENOMEM. Adjust test parameters" 182 fi 183 # We don't know how much of the input we dropped. So just check that 184 # the first ten lines of tail's output are the same as the last ten of 185 # the input 186 jot -w "%01023d" 10 32767 0 -1 > expectfile 187 head -n 10 outfile > outtrunc 188 diff expectfile outtrunc 189 atf_check cmp expectfile outtrunc 190} 191 192atf_test_case longfile_r_longlines 193longfile_r_longlines_head() 194{ 195 atf_set "descr" "Reverse a long file with extremely long lines" 196} 197longfile_r_longlines_body() 198{ 199 jot -s " " -w "%07d" 18000 0 > infile 200 jot -s " " -w "%07d" 18000 18000 >> infile 201 jot -s " " -w "%07d" 18000 36000 >> infile 202 jot -s " " -w "%07d" 18000 36000 > expectfile 203 jot -s " " -w "%07d" 18000 18000 >> expectfile 204 jot -s " " -w "%07d" 18000 0 >> expectfile 205 tail -r infile > outfile 206 tail -r < infile > outpipe 207 atf_check cmp expectfile outfile 208 atf_check cmp expectfile outpipe 209} 210 211atf_test_case longfile_rc135782 212longfile_rc135782_head() 213{ 214 atf_set "descr" "Reverse a long file and print the last 135,782 bytes" 215} 216longfile_rc135782_body() 217{ 218 jot -w "%063d" 9000 0 > infile 219 jot -w "%063d" 2121 8999 0 -1 > expectfile 220 echo "0000000000000000000000000000000006878" >> expectfile 221 tail -rc135782 infile > outfile 222 tail -rc135782 < infile > outpipe 223 atf_check cmp expectfile outfile 224 atf_check cmp expectfile outpipe 225} 226 227atf_test_case longfile_rc145782_longlines 228longfile_rc145782_longlines_head() 229{ 230 atf_set "descr" "Reverse a long file with extremely long lines and print the last 145,782 bytes" 231} 232longfile_rc145782_longlines_body() 233{ 234 jot -s " " -w "%07d" 18000 0 > infile 235 jot -s " " -w "%07d" 18000 18000 >> infile 236 jot -s " " -w "%07d" 18000 36000 >> infile 237 jot -s " " -w "%07d" 18000 36000 > expectfile 238 echo -n "35777 " >> expectfile 239 jot -s " " -w "%07d" 222 35778 >> expectfile 240 tail -rc145782 infile > outfile 241 tail -rc145782 < infile > outpipe 242 atf_check cmp expectfile outfile 243 atf_check cmp expectfile outpipe 244} 245 246atf_test_case longfile_rn2500 247longfile_rn2500_head() 248{ 249 atf_set "descr" "Reverse a long file and print the last 2,500 lines" 250} 251longfile_rn2500_body() 252{ 253 jot -w "%063d" 9000 0 > infile 254 jot -w "%063d" 2500 8999 0 -1 > expectfile 255 tail -rn2500 infile > outfile 256 tail -rn2500 < infile > outpipe 257 atf_check cmp expectfile outfile 258 atf_check cmp expectfile outpipe 259} 260 261atf_test_case broken_pipe 262broken_pipe_head() 263{ 264 atf_set "descr" "Do not print bogus errno based output on short writes" 265} 266broken_pipe_body() 267{ 268 atf_check -o save:ints seq -f '%128g' 1 1000 269 atf_check -s ignore \ 270 -e "inline:tail: stdout\nexit code: 1\n" \ 271 -x '(tail -n 856 ints; echo exit code: $? >&2) | sleep 2' 272} 273 274atf_test_case stdin 275stdin_head() 276{ 277 atf_set "descr" "Check basic operations on standard input" 278} 279stdin_body() 280{ 281 seq 1 5 > infile 282 seq 1 5 > expectfile 283 seq 5 1 > expectfile_r 284 285 tail < infile > outfile 286 tail -r < infile > outfile_r 287 288 atf_check cmp expectfile outfile 289 atf_check cmp expectfile_r outfile_r 290} 291 292atf_test_case follow 293follow_head() 294{ 295 atf_set "descr" "Basic regression test for -f" 296} 297follow_body() 298{ 299 local pid 300 301 seq 1 5 > expectfile 302 seq 1 3 > infile 303 tail -f infile > outfile & 304 pid=$! 305 sleep 0.1 306 seq 4 5 >> infile 307 sleep 0.1 308 atf_check cmp expectfile outfile 309 atf_check kill $pid 310} 311 312atf_test_case follow_stdin 313follow_stdin_head() 314{ 315 atf_set "descr" "Verify that -f works with files piped to standard input" 316} 317follow_stdin_body() 318{ 319 local pid 320 321 seq 1 5 > expectfile 322 seq 1 3 > infile 323 tail -f < infile > outfile & 324 pid=$! 325 sleep 0.1 326 seq 4 5 >> infile 327 sleep 0.1 328 atf_check cmp expectfile outfile 329 atf_check kill $pid 330} 331 332atf_test_case follow_create 333follow_create_head() 334{ 335 atf_set "descr" "Verify that -F works when a file is created" 336} 337follow_create_body() 338{ 339 local pid 340 341 rm -f infile 342 tail -F infile > outfile & 343 pid=$! 344 seq 1 5 >infile 345 sleep 2 346 atf_check cmp infile outfile 347 atf_check kill $pid 348} 349 350atf_test_case follow_rename 351follow_rename_head() 352{ 353 atf_set "descr" "Verify that -F works when a file is replaced" 354} 355follow_rename_body() 356{ 357 local pid 358 359 seq 1 5 > expectfile 360 seq 1 3 > infile 361 tail -F infile > outfile & 362 pid=$! 363 seq 4 5 > infile_new 364 atf_check mv infile infile_old 365 atf_check mv infile_new infile 366 # tail -F polls for a new file every 1s. 367 sleep 2 368 atf_check cmp expectfile outfile 369 atf_check kill $pid 370} 371 372atf_test_case silent_header 373silent_header_head() { 374 atf_set "descr" "Test tail(1)'s silent header feature" 375} 376silent_header_body() { 377 jot 11 1 11 > file1 378 jot 11 2 12 > file2 379 jot 10 2 11 > expectfile 380 jot 10 3 12 >> expectfile 381 tail -q file1 file2 > outfile 382 atf_check cmp outfile expectfile 383} 384 385atf_test_case verbose_header 386verbose_header_head() { 387 atf_set "descr" "Test tail(1)'s verbose header feature" 388} 389verbose_header_body() { 390 jot 11 1 11 > file1 391 echo '==> file1 <==' > expectfile 392 jot 10 2 11 >> expectfile 393 tail -v file1 > outfile 394 atf_check cmp outfile expectfile 395} 396 397atf_test_case si_number 398si_number_head() { 399 atf_set "descr" "Test tail(1)'s SI number feature" 400} 401si_number_body() { 402 jot -b aaaaaaa 129 > file1 403 jot -b aaaaaaa 128 > expectfile 404 tail -c 1k file1 > outfile 405 atf_check cmp outfile expectfile 406 jot 1025 1 1025 > file1 407 jot 1024 2 1025 > expectfile 408 tail -n 1k file1 > outfile 409 atf_check cmp outfile expectfile 410} 411 412atf_test_case no_lf_at_eof 413no_lf_at_eof_head() 414{ 415 atf_set "descr" "File does not end in newline" 416} 417no_lf_at_eof_body() 418{ 419 printf "a\nb\nc" >infile 420 atf_check -o inline:"c" tail -1 infile 421 atf_check -o inline:"b\nc" tail -2 infile 422 atf_check -o inline:"a\nb\nc" tail -3 infile 423 atf_check -o inline:"a\nb\nc" tail -4 infile 424} 425 426atf_init_test_cases() 427{ 428 atf_add_test_case empty_r 429 atf_add_test_case file_r 430 atf_add_test_case file_rc28 431 atf_add_test_case file_rn2 432 atf_add_test_case pipe_leading_newline_r 433 # The longfile tests are designed to exercise behavior in r_buf(), 434 # which operates on 128KB blocks 435 atf_add_test_case longfile_r 436 atf_add_test_case longfile_r_enomem 437 atf_add_test_case longfile_r_longlines 438 atf_add_test_case longfile_rc135782 439 atf_add_test_case longfile_rc145782_longlines 440 atf_add_test_case longfile_rn2500 441 atf_add_test_case broken_pipe 442 atf_add_test_case stdin 443 atf_add_test_case follow 444 atf_add_test_case follow_stdin 445 atf_add_test_case follow_create 446 atf_add_test_case follow_rename 447 atf_add_test_case silent_header 448 atf_add_test_case verbose_header 449 atf_add_test_case si_number 450 atf_add_test_case no_lf_at_eof 451} 452