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. Note that
53 # this is designed to be able to run on BSD systems as well to check
54 # our behavior against theirs (some behavior that is known to be
55 # idiosyncratic to illumos is skipped on non-illumos systems).
61 while [[ $# -gt 0 ]]; do
72 echo "Usage: tailtests.sh" \
73 "[-o <override tail executable>]" \
74 "[-d <override output directory>]"
81 # Shut bash up upon receiving a term so we can drop it on our children
82 # without disrupting the output.
86 echo "$CMD: program is $PROG"
88 if [[ $DIR != "" ]]; then
89 echo "$CMD: directory is $DIR"
93 a
=`echo -e "abcd" | $PROG +2c`
97 a
=`echo "abcd" | $PROG +8c`
101 a
=`echo "abcd" | $PROG -9c`
102 checktest
"$a" "$o" 3
105 a
=`echo -e "x" | $PROG -1l`
106 checktest
"$a" "$o" 4
109 a
=`echo -e "x\ny\n" | $PROG -1l`
110 checktest
"$a" "$o" 5
113 a
=`echo -e "x\ny\n" | $PROG -2l`
114 checktest
"$a" "$o" 6
117 a
=`echo -e "x\ny" | $PROG -1l`
118 checktest
"$a" "$o" 7
121 a
=`echo -e "x\ny\n" | $PROG +1l`
122 checktest
"$a" "$o" 8
125 a
=`echo -e "x\ny\n" | $PROG +2l`
126 checktest
"$a" "$o" 9
129 a
=`echo -e "x" | $PROG -1`
130 checktest
"$a" "$o" 10
133 a
=`echo -e "x\ny\n" | $PROG -1`
134 checktest
"$a" "$o" 11
137 a
=`echo -e "x\ny\n" | $PROG -2`
138 checktest
"$a" "$o" 12
141 a
=`echo -e "x\ny" | $PROG -1`
142 checktest
"$a" "$o" 13
145 a
=`echo -e "x\ny\n" | $PROG +1`
146 checktest
"$a" "$o" 14
149 a
=`echo -e "x\ny\n" | $PROG +2`
150 checktest
"$a" "$o" 15
153 a
=`printf "xyyyyyyyyyyz\n" | $PROG +10c`
154 checktest
"$a" "$o" 16
156 o
=`printf "y\ny\nz\n"`
157 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG +10l`
158 checktest
"$a" "$o" 17
160 o
=`printf "y\ny\ny\ny\ny\ny\ny\ny\ny\nz\n"`
161 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG -10l`
162 checktest
"$a" "$o" 18
164 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\n"`
165 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +10lr`
166 checktest
"$a" "$o" 19
168 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\nf\n"`
169 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -10lr`
170 checktest
"$a" "$o" 20
172 a
=`printf "o\nn\nm\nl\n"`
173 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +10cr`
174 checktest
"$a" "$o" 21
176 a
=`printf "o\nn\nm\nl\nk\n"`
177 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -10cr`
178 checktest
"$a" "$o" 22
181 # For reasons that are presumably as accidental as they are ancient, legacy
182 # (and closed) Solaris tail(1) allows +c, +l and -l to be aliases for +10c,
183 # +10l and -10l, respectively. If we are on SunOS, verify that this silly
184 # behavior is functional.
186 if [[ `uname -s` == "SunOS" ]]; then
188 a
=`printf "xyyyyyyyyyyz\n" | $PROG +c`
189 checktest
"$a" "$o" 16a
191 o
=`printf "y\ny\nz\n"`
192 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG +l`
193 checktest
"$a" "$o" 17a
195 o
=`printf "y\ny\ny\ny\ny\ny\ny\ny\ny\nz\n"`
196 a
=`printf "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz\n" | $PROG -l`
197 checktest
"$a" "$o" 18a
199 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\n"`
201 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +lr`
202 checktest
"$a" "$o" 19a
204 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +l -r`
205 checktest
"$a" "$o" 19a
207 a
=`printf "o\nn\nm\nl\nk\nj\ni\nh\ng\nf\n"`
209 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -lr`
210 checktest
"$a" "$o" 20a
212 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -l -r`
213 checktest
"$a" "$o" 20b
215 a
=`printf "o\nn\nm\nl\n"`
217 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +cr`
218 checktest
"$a" "$o" 21a
220 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG +c -r`
221 checktest
"$a" "$o" 21a
223 a
=`printf "o\nn\nm\nl\nk\n"`
225 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -cr`
226 checktest
"$a" "$o" 22a
228 o
=`printf "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\n" | $PROG -c -r`
229 checktest
"$a" "$o" 22b
232 o
=`echo -e "c\nb\na"`
233 a
=`echo -e "a\nb\nc" | $PROG -r`
234 checktest
"$a" "$o" 23
237 # Now we want to do a series of follow tests.
239 if [[ $DIR == "" ]]; then
240 export TMPDIR
=/var
/tmp
241 tdir
=$
(mktemp
-d -t tailtest.XXXXXXXX ||
exit 1)
243 tdir
=$
(mktemp
-d $DIR/tailtest.XXXXXXXX ||
exit 1)
247 moved
=$tdir/follow.moved
251 # First, verify that following works in its most basic sense.
253 echo -e "a\nb\nc" > $follow
254 $PROG -f $follow > $out 2> /dev
/null
&
257 echo -e "d\ne\nf" >> $follow
262 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
264 checktest
"$a" "$o" 24
268 # Now verify that following correctly follows the file being moved.
270 echo -e "a\nb\nc" > $follow
271 $PROG -f $follow > $out 2> /dev
/null
&
276 echo -e "d\ne\nf" >> $moved
281 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
283 checktest
"$a" "$o" 25
287 # And now truncation with the new offset being less than the old offset.
289 echo -e "a\nb\nc" > $follow
290 $PROG -f $follow > $out 2> /dev
/null
&
293 echo -e "d\ne\nf" >> $follow
295 echo -e "g\nh\ni" > $follow
300 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
302 checktest
"$a" "$o" 26
306 # And truncation with the new offset being greater than the old offset.
308 echo -e "a\nb\nc" > $follow
310 $PROG -f $follow > $out 2> /dev
/null
&
313 echo -e "d\ne\nf" >> $follow
315 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $follow
320 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
322 checktest
"$a" "$o" 27
326 # Verify that we can follow the moved file and correctly see a truncation.
328 echo -e "a\nb\nc" > $follow
329 $PROG -f $follow > $out 2> /dev
/null
&
334 echo -e "d\ne\nf" >> $moved
336 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $moved
341 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
343 checktest
"$a" "$o" 28
347 # Verify that capital-F follow properly deals with truncation
349 echo -e "a\nb\nc" > $follow
350 $PROG -F $follow > $out 2> /dev
/null
&
353 echo -e "d\ne\nf" >> $follow
355 echo -e "g\nh\ni" > $follow
360 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
362 checktest
"$a" "$o" 29
366 # Verify that capital-F follow _won't_ follow the moved file and will
367 # correctly deal with recreation of the original file.
369 echo -e "a\nb\nc" > $follow
370 $PROG -F $follow > $out 2> /dev
/null
&
375 echo -e "x\ny\nz" >> $moved
378 # At this point, tail is polling on stat'ing the missing file; we need to
379 # be sure to sleep long enough after recreating it to know that it will pick
382 echo -e "d\ne\nf" > $follow
387 o
=`echo -e "a\nb\nc\nd\ne\nf\n"`
389 checktest
"$a" "$o" 30
393 # Verify that following two files works.
395 echo -e "one" > $follow
396 echo -e "two" > $moved
397 $PROG -f $follow $moved > $out 2> /dev
/null
&
400 echo -e "three" >> $follow
402 echo -e "four" >> $moved
404 echo -e "five" >> $follow
409 # There is a bug where the content comes before the header lines,
410 # where rlines/mapprint happens before the header. A pain to fix.
411 # In this test, just make sure we see both files change.
428 checktest
"$a" "$o" 31
431 if [[ `uname -s` == "SunOS" ]]; then
433 # Use DTrace to truncate the file between the return from port_get()
434 # and the reassociation of the file object with the port, exposing
435 # any race conditions whereby FILE_TRUNC events are lost.
437 cat /dev
/null
> $follow
438 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
439 #pragma D option destructive
440 #pragma D option quiet
442 pid\$target::port_get:return
446 system("cat /dev/null > $follow");
447 system("prun %d", pid);
452 system("echo %d >> $follow", j++);
462 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
464 checktest
"$a" "$o" 31a
467 cat /dev
/null
> $follow
468 dtrace
-c "$PROG -f $follow" -s /dev
/stdin
> $out <<EOF
469 #pragma D option destructive
470 #pragma D option quiet
472 pid\$target::port_get:return
476 system("mv $follow $moved");
477 system("cat /dev/null > $moved");
478 system("prun %d", pid);
483 system("echo %d >> %s", j++,
484 i < 5 ? "$follow" : "$moved");
494 o
=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
496 checktest
"$a" "$o" 31b
500 # Verify that -F will deal properly with the file being truncated
501 # not by truncation, but rather via an ftruncate() from logadm.
503 cat /dev
/null
> $follow
504 ( $PROG -F $follow > $out ) &
506 echo -e "a\nb\nc\nd\ne\nf" >> $follow
509 echo -e "g\nh\ni" >> $follow
514 o
=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
516 checktest
"$a" "$o" 31c
520 # We're now going to test that while we may miss output due to truncations
521 # occurring faster than tail can read, we don't ever repeat output.
523 cat /dev
/null
> $follow
524 ( $PROG -f $follow > $out ) &
526 ( let i
=0 ; while true
; do echo $i > $follow ; sleep 0.1; let i
=i
+1 ; done ) &
532 a
=`sort $out | uniq -c | sort -n | tail -1 | awk '{ print $1 }'`
535 checktest
"$a" "$o" 32
537 # Test different ways of specifying character offsets
540 a
=`printf "hello\nworld\n" | $PROG -c2`
541 checktest
"$a" "$o" 33
543 a
=`printf "hello\nworld\n" | $PROG -c-2`
544 checktest
"$a" "$o" 34
546 a
=`printf "hello\nworld\n" | $PROG -c 2`
547 checktest
"$a" "$o" 35
549 a
=`printf "hello\nworld\n" | $PROG -c -2`
550 checktest
"$a" "$o" 36
552 a
=`printf "hello\nworld\n" | $PROG -2c`
553 checktest
"$a" "$o" 37
555 o
=`printf "llo\nworld\n"`
557 a
=`printf "hello\nworld\n" | $PROG -c +3`
558 checktest
"$a" "$o" 38
560 a
=`printf "hello\nworld\n" | $PROG -c+3`
561 checktest
"$a" "$o" 39
563 a
=`printf "hello\nworld\n" | $PROG +3c`
564 checktest
"$a" "$o" 40
566 # Test various ways of specifying block offsets
569 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b1`
570 checktest
"$a" "$o" 41
572 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b 1`
573 checktest
"$a" "$o" 42
575 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b -1`
576 checktest
"$a" "$o" 43
578 a
=`printf "${BLOCK//./x}$BLOCK" | $PROG -b +2`
579 checktest
"$a" "$o" 44
581 # Test that illegal arguments aren't allowed
594 echo "$CMD: completed"