4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
9 # A full copy of the text of the CDDL should have accompanied this
10 # source. A copy is of the CDDL is also available via the Internet
11 # at http://www.illumos.org/license/CDDL.
15 # Copyright 2010 Chris Love. All rights reserved.
16 # Copyright 2017, Joyent, Inc.
31 if [[ "$actual" != "$output" ]]; then
32 echo "$CMD: test $test: FAIL"
33 echo -e "$CMD: test $test: expected output:\n$output"
34 echo -e "$CMD: test $test: actual output:\n$actual"
36 echo "$CMD: test $test: pass"
42 printf "foobar" |
$PROG $
* &> /dev
/null
44 if [[ $?
-eq 0 ]]; then
45 printf '%s: test "test %s": was supposed to fail\n' "$CMD" "$*"
47 printf '%s: test "%s": pass\n' "$CMD" "$*"
52 # Test cases for 'tail', some based on CoreUtils test cases (validated
53 # with legacy Solaris 'tail' and/or xpg4 'tail'). Note that this is designed
54 # to be able to run on BSD systems as well to check our behavior against
55 # theirs (some behavior that is known to be idiosyncratic to illumos is
56 # skipped on non-illumos systems).
62 while [[ $# -gt 0 ]]; do
65 PROG
=/usr
/xpg
4/bin
/tail
77 echo "Usage: tailtests.sh" \
78 "[-x][-o <override tail executable>]" \
79 "[-d <override output directory>]"
86 # Shut bash up upon receiving a term so we can drop it on our children
87 # without disrupting the output.
91 echo "$CMD: program is $PROG"
93 if [[ $DIR != "" ]]; then
94 echo "$CMD: directory is $DIR"
98 a
=`echo -e "abcd" | $PROG +2c`
102 a
=`echo "abcd" | $PROG +8c`
103 checktest
"$a" "$o" 2
106 a
=`echo "abcd" | $PROG -9c`
107 checktest
"$a" "$o" 3
110 a
=`echo -e "x" | $PROG -1l`
111 checktest
"$a" "$o" 4
114 a
=`echo -e "x\ny\n" | $PROG -1l`
115 checktest
"$a" "$o" 5
118 a
=`echo -e "x\ny\n" | $PROG -2l`
119 checktest
"$a" "$o" 6
122 a
=`echo -e "x\ny" | $PROG -1l`
123 checktest
"$a" "$o" 7
126 a
=`echo -e "x\ny\n" | $PROG +1l`
127 checktest
"$a" "$o" 8
130 a
=`echo -e "x\ny\n" | $PROG +2l`
131 checktest
"$a" "$o" 9
134 a
=`echo -e "x" | $PROG -1`
135 checktest
"$a" "$o" 10
138 a
=`echo -e "x\ny\n" | $PROG -1`
139 checktest
"$a" "$o" 11
142 a
=`echo -e "x\ny\n" | $PROG -2`
143 checktest
"$a" "$o" 12
146 a
=`echo -e "x\ny" | $PROG -1`
147 checktest
"$a" "$o" 13
150 a
=`echo -e "x\ny\n" | $PROG +1`
151 checktest
"$a" "$o" 14
154 a
=`echo -e "x\ny\n" | $PROG +2`
155 checktest
"$a" "$o" 15
158 a
=`printf "xyyyyyyyyyyz\n" | $PROG +10c`
159 checktest
"$a" "$o" 16
161 o
=`printf "y\ny\nz\n"`
162 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG +10l`
163 checktest
"$a" "$o" 17
165 o
=`printf "y\ny\ny\ny\ny\ny\ny\ny\ny\nz\n"`
166 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG -10l`
167 checktest
"$a" "$o" 18
169 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\n"`
170 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +10lr`
171 checktest
"$a" "$o" 19
173 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\nf\n"`
174 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -10lr`
175 checktest
"$a" "$o" 20
177 a
=`printf "o\nn\nm\nl\n"`
178 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +10cr`
179 checktest
"$a" "$o" 21
181 a
=`printf "o\nn\nm\nl\nk\n"`
182 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -10cr`
183 checktest
"$a" "$o" 22
186 # For reasons that are presumably as accidental as they are ancient, legacy
187 # (and closed) Solaris tail(1) allows +c, +l and -l to be aliases for +10c,
188 # +10l and -10l, respectively. If we are on SunOS, verify that this silly
189 # behavior is functional.
191 if [[ `uname -s` == "SunOS" ]]; then
193 a
=`printf "xyyyyyyyyyyz\n" | $PROG +c`
194 checktest
"$a" "$o" 16a
196 o
=`printf "y\ny\nz\n"`
197 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG +l`
198 checktest
"$a" "$o" 17a
200 o
=`printf "y\ny\ny\ny\ny\ny\ny\ny\ny\nz\n"`
201 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG -l`
202 checktest
"$a" "$o" 18a
204 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\n"`
206 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +lr`
207 checktest
"$a" "$o" 19a
209 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +l -r`
210 checktest
"$a" "$o" 19a
212 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\nf\n"`
214 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -lr`
215 checktest
"$a" "$o" 20a
217 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -l -r`
218 checktest
"$a" "$o" 20b
220 a
=`printf "o\nn\nm\nl\n"`
222 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +cr`
223 checktest
"$a" "$o" 21a
225 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +c -r`
226 checktest
"$a" "$o" 21a
228 a
=`printf "o\nn\nm\nl\nk\n"`
230 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -cr`
231 checktest
"$a" "$o" 22a
233 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -c -r`
234 checktest
"$a" "$o" 22b
237 o
=`echo -e "c\nb\na"`
238 a
=`echo -e "a\nb\nc" | $PROG -r`
239 checktest
"$a" "$o" 23
242 # Now we want to do a series of follow tests.
244 if [[ $DIR == "" ]]; then
245 export TMPDIR
=/var
/tmp
246 tdir
=$
(mktemp
-d -t tailtest.XXXXXXXX ||
exit 1)
248 tdir
=$
(mktemp
-d $DIR/tailtest.XXXXXXXX ||
exit 1)
252 moved
=$tdir/follow.moved
256 # First, verify that following works in its most basic sense.
258 echo -e "a\nb\nc" > $follow
259 $PROG -f $follow > $out 2> /dev
/null
&
262 echo -e "d\ne\nf" >> $follow
267 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
269 checktest
"$a" "$o" 24
273 # Now verify that following correctly follows the file being moved.
275 echo -e "a\nb\nc" > $follow
276 $PROG -f $follow > $out 2> /dev
/null
&
281 echo -e "d\ne\nf" >> $moved
286 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
288 checktest
"$a" "$o" 25
292 # And now truncation with the new offset being less than the old offset.
294 echo -e "a\nb\nc" > $follow
295 $PROG -f $follow > $out 2> /dev
/null
&
298 echo -e "d\ne\nf" >> $follow
300 echo -e "g\nh\ni" > $follow
305 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
307 checktest
"$a" "$o" 26
311 # And truncation with the new offset being greater than the old offset.
313 echo -e "a\nb\nc" > $follow
315 $PROG -f $follow > $out 2> /dev
/null
&
318 echo -e "d\ne\nf" >> $follow
320 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $follow
325 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
327 checktest
"$a" "$o" 27
331 # Verify that we can follow the moved file and correctly see a truncation.
333 echo -e "a\nb\nc" > $follow
334 $PROG -f $follow > $out 2> /dev
/null
&
339 echo -e "d\ne\nf" >> $moved
341 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $moved
346 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
348 checktest
"$a" "$o" 28
352 # Verify that capital-F follow properly deals with truncation
354 echo -e "a\nb\nc" > $follow
355 $PROG -F $follow > $out 2> /dev
/null
&
358 echo -e "d\ne\nf" >> $follow
360 echo -e "g\nh\ni" > $follow
365 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
367 checktest
"$a" "$o" 29
371 # Verify that capital-F follow _won't_ follow the moved file and will
372 # correctly deal with recreation of the original file.
374 echo -e "a\nb\nc" > $follow
375 $PROG -F $follow > $out 2> /dev
/null
&
380 echo -e "x\ny\nz" >> $moved
383 # At this point, tail is polling on stat'ing the missing file; we need to
384 # be sure to sleep long enough after recreating it to know that it will pick
387 echo -e "d\ne\nf" > $follow
392 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
394 checktest
"$a" "$o" 30
398 # Verify that following two files works.
400 echo -e "one" > $follow
401 echo -e "two" > $moved
402 $PROG -f $follow $moved > $out 2> /dev
/null
&
405 echo -e "three" >> $follow
407 echo -e "four" >> $moved
409 echo -e "five" >> $follow
414 # There is a bug where the content comes before the header lines,
415 # where rlines/mapprint happens before the header. A pain to fix.
416 # In this test, just make sure we see both files change.
433 checktest
"$a" "$o" 31
436 if [[ `uname -s` == "SunOS" ]]; then
438 # Use DTrace to truncate the file between the return from port_get()
439 # and the reassociation of the file object with the port, exposing
440 # any race conditions whereby FILE_TRUNC events are lost.
442 cat /dev
/null
> $follow
443 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
444 #pragma D option destructive
445 #pragma D option quiet
447 pid\$target::port_get:return
451 system("cat /dev/null > $follow");
452 system("prun %d", pid);
457 system("echo %d >> $follow", j++);
467 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
469 checktest
"$a" "$o" 31a
472 cat /dev
/null
> $follow
473 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
474 #pragma D option destructive
475 #pragma D option quiet
477 pid\$target::port_get:return
481 system("mv $follow $moved");
482 system("cat /dev/null > $moved");
483 system("prun %d", pid);
488 system("echo %d >> %s", j++,
489 i < 5 ? "$follow" : "$moved");
499 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
501 checktest
"$a" "$o" 31b
505 # Verify that -F will deal properly with the file being truncated
506 # not by truncation, but rather via an ftruncate() from logadm.
508 cat /dev
/null
> $follow
509 ( $PROG -F $follow > $out ) &
511 echo -e "a\nb\nc\nd\ne\nf" >> $follow
514 echo -e "g\nh\ni" >> $follow
519 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
521 checktest
"$a" "$o" 31c
525 # We're now going to test that while we may miss output due to truncations
526 # occurring faster than tail can read, we don't ever repeat output.
528 cat /dev
/null
> $follow
529 ( $PROG -f $follow > $out ) &
531 ( let i
=0 ; while true
; do echo $i > $follow ; sleep 0.1; let i
=i
+1 ; done ) &
537 a
=`sort $out | uniq -c | sort -n | tail -1 | awk '{ print $1 }'`
540 checktest
"$a" "$o" 32
542 # Test different ways of specifying character offsets
545 a
=`printf "hello\nworld\n" | $PROG -c2`
546 checktest
"$a" "$o" 33
548 a
=`printf "hello\nworld\n" | $PROG -c-2`
549 checktest
"$a" "$o" 34
551 a
=`printf "hello\nworld\n" | $PROG -c 2`
552 checktest
"$a" "$o" 35
554 a
=`printf "hello\nworld\n" | $PROG -c -2`
555 checktest
"$a" "$o" 36
557 a
=`printf "hello\nworld\n" | $PROG -2c`
558 checktest
"$a" "$o" 37
560 o
=`printf "llo\nworld\n"`
562 a
=`printf "hello\nworld\n" | $PROG -c +3`
563 checktest
"$a" "$o" 38
565 a
=`printf "hello\nworld\n" | $PROG -c+3`
566 checktest
"$a" "$o" 39
568 a
=`printf "hello\nworld\n" | $PROG +3c`
569 checktest
"$a" "$o" 40
571 # Test various ways of specifying block offsets
574 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b1`
575 checktest
"$a" "$o" 41
577 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b 1`
578 checktest
"$a" "$o" 42
580 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b -1`
581 checktest
"$a" "$o" 43
583 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b +2`
584 checktest
"$a" "$o" 44
586 # Test that illegal arguments aren't allowed
599 echo "$CMD: completed"