xref: /freebsd/usr.bin/tail/tests/tail_test.sh (revision c8e7f78a3d28ff6e6223ed136ada8e1e2f34965e)
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