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 (c) 2013, Joyent, Inc. All rights reserved.
25 if [[ "$actual" != "$output" ]]; then
26 echo "$CMD: test $test: FAIL"
27 echo -e "$CMD: test $test: expected output:\n$output"
28 echo -e "$CMD: test $test: actual output:\n$actual"
30 echo "$CMD: test $test: pass"
35 # Test cases for 'tail', some based on CoreUtils test cases. Note that
36 # this is designed to be able to run on BSD systems as well to check
37 # our behavior against theirs (some behavior that is known to be
38 # idiosyncratic to illumos is skipped on non-illumos systems).
44 while [[ $# -gt 0 ]]; do
55 echo "Usage: tailtests.sh" \
56 "[-o <override tail executable>]" \
57 "[-d <override output directory>]"
64 # Shut bash up upon receiving a term so we can drop it on our children
65 # without disrupting the output.
69 echo "$CMD: program is $PROG"
71 if [[ $DIR != "" ]]; then
72 echo "$CMD: directory is $DIR"
76 a
=`echo -e "abcd" | $PROG +2c`
80 a
=`echo "abcd" | $PROG +8c`
84 a
=`echo "abcd" | $PROG -9c`
88 a
=`echo -e "x" | $PROG -1l`
92 a
=`echo -e "x\ny\n" | $PROG -1l`
96 a
=`echo -e "x\ny\n" | $PROG -2l`
100 a
=`echo -e "x\ny" | $PROG -1l`
101 checktest
"$a" "$o" 7
104 a
=`echo -e "x\ny\n" | $PROG +1l`
105 checktest
"$a" "$o" 8
108 a
=`echo -e "x\ny\n" | $PROG +2l`
109 checktest
"$a" "$o" 9
112 a
=`echo -e "x" | $PROG -1`
113 checktest
"$a" "$o" 10
116 a
=`echo -e "x\ny\n" | $PROG -1`
117 checktest
"$a" "$o" 11
120 a
=`echo -e "x\ny\n" | $PROG -2`
121 checktest
"$a" "$o" 12
124 a
=`echo -e "x\ny" | $PROG -1`
125 checktest
"$a" "$o" 13
128 a
=`echo -e "x\ny\n" | $PROG +1`
129 checktest
"$a" "$o" 14
132 a
=`echo -e "x\ny\n" | $PROG +2`
133 checktest
"$a" "$o" 15
136 a
=`echo -e "xyyyyyyyyyyz" | $PROG +10c`
137 checktest
"$a" "$o" 16
139 o
=`echo -e "y\ny\nz"`
140 a
=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG +10l`
141 checktest
"$a" "$o" 17
143 o
=`echo -e "y\ny\ny\ny\ny\ny\ny\ny\ny\nz"`
144 a
=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG -10l`
145 checktest
"$a" "$o" 18
148 # For reasons that are presumably as accidental as they are ancient, legacy
149 # (and closed) Solaris tail(1) allows +c, +l and -l to be aliases for +10c,
150 # +10l and -10l, respectively. If we are on SunOS, verify that this silly
151 # behavior is functional.
153 if [[ `uname -s` == "SunOS" ]]; then
155 a
=`echo -e "xyyyyyyyyyyz" | $PROG +c`
156 checktest
"$a" "$o" 16a
158 o
=`echo -e "y\ny\nz"`
159 a
=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG +l`
160 checktest
"$a" "$o" 17a
162 o
=`echo -e "y\ny\ny\ny\ny\ny\ny\ny\ny\nz"`
163 a
=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG -l`
164 checktest
"$a" "$o" 18a
167 o
=`echo -e "c\nb\na"`
168 a
=`echo -e "a\nb\nc" | $PROG -r`
169 checktest
"$a" "$o" 19
172 # Now we want to do a series of follow tests.
174 if [[ $DIR == "" ]]; then
175 export TMPDIR
=/var
/tmp
176 tdir
=$
(mktemp
-d -t tailtest.XXXXXXXX ||
exit 1)
178 tdir
=$
(mktemp
-d $DIR/tailtest.XXXXXXXX ||
exit 1)
182 moved
=$tdir/follow.moved
186 # First, verify that following works in its most basic sense.
188 echo -e "a\nb\nc" > $follow
189 $PROG -f $follow > $out 2> /dev
/null
&
192 echo -e "d\ne\nf" >> $follow
197 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
199 checktest
"$a" "$o" 20
203 # Now verify that following correctly follows the file being moved.
205 echo -e "a\nb\nc" > $follow
206 $PROG -f $follow > $out 2> /dev
/null
&
211 echo -e "d\ne\nf" >> $moved
216 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
218 checktest
"$a" "$o" 21
222 # And now truncation with the new offset being less than the old offset.
224 echo -e "a\nb\nc" > $follow
225 $PROG -f $follow > $out 2> /dev
/null
&
228 echo -e "d\ne\nf" >> $follow
230 echo -e "g\nh\ni" > $follow
235 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
237 checktest
"$a" "$o" 22
241 # And truncation with the new offset being greater than the old offset.
243 echo -e "a\nb\nc" > $follow
245 $PROG -f $follow > $out 2> /dev
/null
&
248 echo -e "d\ne\nf" >> $follow
250 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $follow
255 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
257 checktest
"$a" "$o" 23
261 # Verify that we can follow the moved file and correctly see a truncation.
263 echo -e "a\nb\nc" > $follow
264 $PROG -f $follow > $out 2> /dev
/null
&
269 echo -e "d\ne\nf" >> $moved
271 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $moved
276 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
278 checktest
"$a" "$o" 24
282 # Verify that capital-F follow properly deals with truncation
284 echo -e "a\nb\nc" > $follow
285 $PROG -F $follow > $out 2> /dev
/null
&
288 echo -e "d\ne\nf" >> $follow
290 echo -e "g\nh\ni" > $follow
295 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
297 checktest
"$a" "$o" 25
301 # Verify that capital-F follow _won't_ follow the moved file and will
302 # correctly deal with recreation of the original file.
304 echo -e "a\nb\nc" > $follow
305 $PROG -F $follow > $out 2> /dev
/null
&
310 echo -e "x\ny\nz" >> $moved
313 # At this point, tail is polling on stat'ing the missing file; we need to
314 # be sure to sleep long enough after recreating it to know that it will pick
317 echo -e "d\ne\nf" > $follow
322 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
324 checktest
"$a" "$o" 26
328 # Verify that following two files works.
330 echo -e "one" > $follow
331 echo -e "two" > $moved
332 $PROG -f $follow $moved > $out 2> /dev
/null
&
335 echo -e "three" >> $follow
337 echo -e "four" >> $moved
339 echo -e "five" >> $follow
344 # There is a bug where the content comes before the header lines,
345 # where rlines/mapprint happens before the header. A pain to fix.
346 # In this test, just make sure we see both files change.
363 checktest
"$a" "$o" 27
366 if [[ `uname -s` == "SunOS" ]]; then
368 # Use DTrace to truncate the file between the return from port_get()
369 # and the reassociation of the file object with the port, exposing
370 # any race conditions whereby FILE_TRUNC events are lost.
372 cat /dev
/null
> $follow
373 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
374 #pragma D option destructive
375 #pragma D option quiet
377 pid\$target::port_get:return
381 system("cat /dev/null > $follow");
382 system("prun %d", pid);
387 system("echo %d >> $follow", j++);
397 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
399 checktest
"$a" "$o" 27a
402 cat /dev
/null
> $follow
403 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
404 #pragma D option destructive
405 #pragma D option quiet
407 pid\$target::port_get:return
411 system("mv $follow $moved");
412 system("cat /dev/null > $moved");
413 system("prun %d", pid);
418 system("echo %d >> %s", j++,
419 i < 5 ? "$follow" : "$moved");
429 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
431 checktest
"$a" "$o" 27b
435 # Verify that -F will deal properly with the file being truncated
436 # not by truncation, but rather via an ftruncate() from logadm.
438 cat /dev
/null
> $follow
439 ( $PROG -F $follow > $out ) &
441 echo -e "a\nb\nc\nd\ne\nf" >> $follow
444 echo -e "g\nh\ni" >> $follow
449 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
451 checktest
"$a" "$o" 27c
455 # We're now going to test that while we may miss output due to truncations
456 # occurring faster than tail can read, we don't ever repeat output.
458 cat /dev
/null
> $follow
459 ( $PROG -f $follow > $out ) &
461 ( let i
=0 ; while true
; do echo $i > $follow ; sleep 0.1; let i
=i
+1 ; done ) &
467 a
=`sort $out | uniq -c | sort -n | tail -1 | awk '{ print $1 }'`
470 checktest
"$a" "$o" 28
472 echo "$CMD: completed"