add UNLEASHED_OBJ to unleashed.mk
[unleashed/tickless.git] / usr / src / cmd / tail / tests / tailtests.sh
blobd2a58a5ca644cb9fe4ede31eff8269318f5166a1
1 #!/bin/bash
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
7 # 1.0 of the CDDL.
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.
19 checktest()
21 local actual=$1
22 local output=$2
23 local test=$3
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"
29 else
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).
40 PROG=/usr/bin/tail
41 CMD=`basename $0`
42 DIR=""
44 while [[ $# -gt 0 ]]; do
45 case $1 in
46 -o)
47 PROG=$2
48 shift 2
50 -d)
51 DIR=$2
52 shift 2
55 echo "Usage: tailtests.sh" \
56 "[-o <override tail executable>]" \
57 "[-d <override output directory>]"
58 exit 1
60 esac
61 done
64 # Shut bash up upon receiving a term so we can drop it on our children
65 # without disrupting the output.
67 trap "exit 0" TERM
69 echo "$CMD: program is $PROG"
71 if [[ $DIR != "" ]]; then
72 echo "$CMD: directory is $DIR"
75 o=`echo -e "bcd"`
76 a=`echo -e "abcd" | $PROG +2c`
77 checktest "$a" "$o" 1
79 o=`echo -e ""`
80 a=`echo "abcd" | $PROG +8c`
81 checktest "$a" "$o" 2
83 o=`echo -e "abcd"`
84 a=`echo "abcd" | $PROG -9c`
85 checktest "$a" "$o" 3
87 o=`echo -e "x"`
88 a=`echo -e "x" | $PROG -1l`
89 checktest "$a" "$o" 4
91 o=`echo -e "\n"`
92 a=`echo -e "x\ny\n" | $PROG -1l`
93 checktest "$a" "$o" 5
95 o=`echo -e "y\n"`
96 a=`echo -e "x\ny\n" | $PROG -2l`
97 checktest "$a" "$o" 6
99 o=`echo -e "y"`
100 a=`echo -e "x\ny" | $PROG -1l`
101 checktest "$a" "$o" 7
103 o=`echo -e "x\ny\n"`
104 a=`echo -e "x\ny\n" | $PROG +1l`
105 checktest "$a" "$o" 8
107 o=`echo -e "y\n"`
108 a=`echo -e "x\ny\n" | $PROG +2l`
109 checktest "$a" "$o" 9
111 o=`echo -e "x"`
112 a=`echo -e "x" | $PROG -1`
113 checktest "$a" "$o" 10
115 o=`echo -e "\n"`
116 a=`echo -e "x\ny\n" | $PROG -1`
117 checktest "$a" "$o" 11
119 o=`echo -e "y\n"`
120 a=`echo -e "x\ny\n" | $PROG -2`
121 checktest "$a" "$o" 12
123 o=`echo -e "y"`
124 a=`echo -e "x\ny" | $PROG -1`
125 checktest "$a" "$o" 13
127 o=`echo -e "x\ny\n"`
128 a=`echo -e "x\ny\n" | $PROG +1`
129 checktest "$a" "$o" 14
131 o=`echo -e "y\n"`
132 a=`echo -e "x\ny\n" | $PROG +2`
133 checktest "$a" "$o" 15
135 o=`echo -e "yyz"`
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
154 o=`echo -e "yyz"`
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)
177 else
178 tdir=$(mktemp -d $DIR/tailtest.XXXXXXXX || exit 1)
181 follow=$tdir/follow
182 moved=$tdir/follow.moved
183 out=$tdir/out
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 &
190 child=$!
191 sleep 2
192 echo -e "d\ne\nf" >> $follow
193 sleep 1
194 kill $child
195 sleep 1
197 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
198 a=`cat $out`
199 checktest "$a" "$o" 20
200 rm $follow
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 &
207 child=$!
208 sleep 2
209 mv $follow $moved
211 echo -e "d\ne\nf" >> $moved
212 sleep 1
213 kill $child
214 sleep 1
216 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
217 a=`cat $out`
218 checktest "$a" "$o" 21
219 rm $moved
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 &
226 child=$!
227 sleep 2
228 echo -e "d\ne\nf" >> $follow
229 sleep 1
230 echo -e "g\nh\ni" > $follow
231 sleep 1
232 kill $child
233 sleep 1
235 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
236 a=`cat $out`
237 checktest "$a" "$o" 22
238 rm $follow
241 # And truncation with the new offset being greater than the old offset.
243 echo -e "a\nb\nc" > $follow
244 sleep 1
245 $PROG -f $follow > $out 2> /dev/null &
246 child=$!
247 sleep 2
248 echo -e "d\ne\nf" >> $follow
249 sleep 1
250 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $follow
251 sleep 1
252 kill $child
253 sleep 1
255 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
256 a=`cat $out`
257 checktest "$a" "$o" 23
258 rm $follow
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 &
265 child=$!
266 sleep 2
267 mv $follow $moved
269 echo -e "d\ne\nf" >> $moved
270 sleep 1
271 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $moved
272 sleep 1
273 kill $child
274 sleep 1
276 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
277 a=`cat $out`
278 checktest "$a" "$o" 24
279 rm $moved
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 &
286 child=$!
287 sleep 2
288 echo -e "d\ne\nf" >> $follow
289 sleep 1
290 echo -e "g\nh\ni" > $follow
291 sleep 1
292 kill $child
293 sleep 1
295 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
296 a=`cat $out`
297 checktest "$a" "$o" 25
298 rm $follow
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 &
306 child=$!
307 sleep 2
308 mv $follow $moved
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
315 # it up.
317 echo -e "d\ne\nf" > $follow
318 sleep 5
319 kill $child
320 sleep 1
322 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
323 a=`cat $out`
324 checktest "$a" "$o" 26
325 rm $moved
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 &
333 child=$!
334 sleep 2
335 echo -e "three" >> $follow
336 sleep 1
337 echo -e "four" >> $moved
338 sleep 1
339 echo -e "five" >> $follow
340 sleep 1
341 kill $child
342 sleep 1
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.
347 o="one
349 ==> $follow <==
352 ==> $moved <==
354 ==> $follow <==
355 three
357 ==> $moved <==
358 four
360 ==> $follow <==
361 five"
362 a=`cat $out`
363 checktest "$a" "$o" 27
364 rm $follow $moved
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
378 /++i == 5/
380 stop();
381 system("cat /dev/null > $follow");
382 system("prun %d", pid);
385 tick-1sec
387 system("echo %d >> $follow", j++);
390 tick-1sec
391 /j == 10/
393 exit(0);
397 o=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
398 a=`cat $out`
399 checktest "$a" "$o" 27a
400 rm $follow
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
408 /++i == 5/
410 stop();
411 system("mv $follow $moved");
412 system("cat /dev/null > $moved");
413 system("prun %d", pid);
416 tick-1sec
418 system("echo %d >> %s", j++,
419 i < 5 ? "$follow" : "$moved");
422 tick-1sec
423 /j == 10/
425 exit(0);
429 o=`echo -e "0\n1\n2\n3\n5\n6\n7\n8\n9\n"`
430 a=`cat $out`
431 checktest "$a" "$o" 27b
432 rm $moved
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 ) &
440 child=$!
441 echo -e "a\nb\nc\nd\ne\nf" >> $follow
442 logadm -c $follow
443 sleep 2
444 echo -e "g\nh\ni" >> $follow
445 sleep 2
446 kill $child
447 sleep 1
449 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
450 a=`cat $out`
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 ) &
460 tchild=$!
461 ( let i=0 ; while true; do echo $i > $follow ; sleep 0.1; let i=i+1 ; done ) &
462 child=$!
463 sleep 10
464 kill $tchild
465 kill $child
467 a=`sort $out | uniq -c | sort -n | tail -1 | awk '{ print $1 }'`
470 checktest "$a" "$o" 28
472 echo "$CMD: completed"
474 exit $errs