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