1 #!/bin/bash
   2 #
   3 #
   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.
   8 #
   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.
  12 #
  13 
  14 #
  15 # Copyright 2010 Chris Love.  All rights reserved.
  16 # Copyright (c) 2013, Joyent, Inc. All rights reserved.
  17 #
  18 
  19 checktest()
  20 {
  21         local actual=$1
  22         local output=$2
  23         local test=$3
  24 
  25         if [[ "$actual" != "$output" ]]; then
  26                 echo "$CMD: test $test: FAIL"
  27                 echo -e "$CMD: test $test: expected output:\n$o"
  28                 echo -e "$CMD: test $test: actual output:\n$a"
  29         else
  30                 echo "$CMD: test $test: pass"
  31         fi
  32 }
  33 
  34 # 
  35 # Test cases for 'tail', some based on CoreUtils test cases (validated
  36 # with legacy Solaris 'tail' and/or xpg4 'tail').  Note that this is designed
  37 # to be able to run on BSD systems as well to check our behavior against
  38 # theirs (some behavior that is known to be idiosyncratic to illumos is
  39 # skipped on non-illumos systems).
  40 #
  41 PROG=/usr/bin/tail
  42 CMD=`basename $0`
  43 DIR=""
  44 
  45 while [[ $# -gt 0 ]]; do
  46         case $1 in
  47             -x)
  48                 PROG=/usr/xpg4/bin/tail
  49                 shift
  50                 ;;
  51             -o)
  52                 PROG=$2
  53                 shift 2
  54                 ;;
  55             -d)
  56                 DIR=$2
  57                 shift 2
  58                 ;;
  59             *)
  60                 echo "Usage: tailtests.sh" \
  61                     "[-x][-o <override tail executable>]" \
  62                     "[-d <override output directory>]"
  63                 exit 1
  64                 ;;
  65         esac
  66 done
  67 
  68 #
  69 # Shut bash up upon receiving a term so we can drop it on our children
  70 # without disrupting the output.
  71 #
  72 trap "exit 0" TERM
  73 
  74 echo "$CMD: program is $PROG"
  75 
  76 if [[ $DIR != "" ]]; then
  77         echo "$CMD: directory is $DIR"
  78 fi
  79 
  80 o=`echo -e "bcd"`
  81 a=`echo -e "abcd" | $PROG +2c`
  82 checktest "$a" "$o" 1
  83 
  84 o=`echo -e ""`
  85 a=`echo "abcd" | $PROG +8c`
  86 checktest "$a" "$o" 2
  87 
  88 o=`echo -e "abcd"`
  89 a=`echo "abcd" | $PROG -9c`
  90 checktest "$a" "$o" 3
  91 
  92 o=`echo -e "x"`
  93 a=`echo -e "x" | $PROG -1l`
  94 checktest "$a" "$o" 4
  95 
  96 o=`echo -e "\n"`
  97 a=`echo -e "x\ny\n" | $PROG -1l`
  98 checktest "$a" "$o" 5
  99 
 100 o=`echo -e "y\n"`
 101 a=`echo -e "x\ny\n" | $PROG -2l`
 102 checktest "$a" "$o" 6
 103 
 104 o=`echo -e "y"`
 105 a=`echo -e "x\ny" | $PROG -1l`
 106 checktest "$a" "$o" 7
 107 
 108 o=`echo -e "x\ny\n"`
 109 a=`echo -e "x\ny\n" | $PROG +1l`
 110 checktest "$a" "$o" 8
 111 
 112 o=`echo -e "y\n"`
 113 a=`echo -e "x\ny\n" | $PROG +2l`
 114 checktest "$a" "$o" 9
 115 
 116 o=`echo -e "x"`
 117 a=`echo -e "x" | $PROG -1`
 118 checktest "$a" "$o" 10
 119 
 120 o=`echo -e "\n"`
 121 a=`echo -e "x\ny\n" | $PROG -1`
 122 checktest "$a" "$o" 11
 123 
 124 o=`echo -e "y\n"`
 125 a=`echo -e "x\ny\n" | $PROG -2`
 126 checktest "$a" "$o" 12
 127 
 128 o=`echo -e "y"`
 129 a=`echo -e "x\ny" | $PROG -1`
 130 checktest "$a" "$o" 13
 131 
 132 o=`echo -e "x\ny\n"`
 133 a=`echo -e "x\ny\n" | $PROG +1`
 134 checktest "$a" "$o" 14
 135 
 136 o=`echo -e "y\n"`
 137 a=`echo -e "x\ny\n" | $PROG +2`
 138 checktest "$a" "$o" 15
 139 
 140 o=`echo -e "yyz"`
 141 a=`echo -e "xyyyyyyyyyyz" | $PROG +10c`
 142 checktest "$a" "$o" 16
 143 
 144 o=`echo -e "y\ny\nz"`
 145 a=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG +10l`
 146 checktest "$a" "$o" 17
 147 
 148 o=`echo -e "y\ny\ny\ny\ny\ny\ny\ny\ny\nz"`
 149 a=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG -10l`
 150 checktest "$a" "$o" 18
 151 
 152 #
 153 # For reasons that are presumably as accidental as they are ancient, legacy
 154 # (and closed) Solaris tail(1) allows +c, +l and -l to be aliases for +10c,
 155 # +10l and -10l, respectively.  If we are on SunOS, verify that this silly
 156 # behavior is functional.
 157 #
 158 if [[ `uname -s` == "SunOS" ]]; then
 159         o=`echo -e "yyz"`
 160         a=`echo -e "xyyyyyyyyyyz" | $PROG +c`
 161         checktest "$a" "$o" 16a
 162 
 163         o=`echo -e "y\ny\nz"`
 164         a=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG +l`
 165         checktest "$a" "$o" 17a
 166 
 167         o=`echo -e "y\ny\ny\ny\ny\ny\ny\ny\ny\nz"`
 168         a=`echo -e "x\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\nz" | $PROG -l`
 169         checktest "$a" "$o" 18a
 170 fi
 171 
 172 o=`echo -e "c\nb\na"`
 173 a=`echo -e "a\nb\nc" | $PROG -r`
 174 checktest "$a" "$o" 19
 175 
 176 #
 177 # Now we want to do a series of follow tests.
 178 #
 179 if [[ $DIR == "" ]]; then
 180         tdir=$(mktemp -d -t tailtest.XXXXXXXX || exit 1)
 181 else
 182         tdir=$(mktemp -d $DIR/tailtest.XXXXXXXX || exit 1)
 183 fi
 184 
 185 follow=$tdir/follow
 186 moved=$tdir/follow.moved
 187 out=$tdir/out
 188 
 189 #
 190 # First, verify that following works in its most basic sense.
 191 #
 192 echo -e "a\nb\nc" > $follow
 193 $PROG -f $follow > $out 2> /dev/null &
 194 child=$!
 195 sleep 2
 196 echo -e "d\ne\nf" >> $follow
 197 sleep 1
 198 kill $child
 199 sleep 1
 200 
 201 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
 202 a=`cat $out`
 203 checktest "$a" "$o" 20
 204 rm $follow
 205 
 206 #
 207 # Now verify that following correctly follows the file being moved.
 208 #
 209 echo -e "a\nb\nc" > $follow
 210 $PROG -f $follow > $out 2> /dev/null &
 211 child=$!
 212 sleep 2
 213 mv $follow $moved
 214 
 215 echo -e "d\ne\nf" >> $moved
 216 sleep 1
 217 kill $child
 218 sleep 1
 219 
 220 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
 221 a=`cat $out`
 222 checktest "$a" "$o" 21
 223 rm $moved
 224 
 225 #
 226 # And now truncation with the new offset being less than the old offset.
 227 #
 228 echo -e "a\nb\nc" > $follow
 229 $PROG -f $follow > $out 2> /dev/null &
 230 child=$!
 231 sleep 2
 232 echo -e "d\ne\nf" >> $follow
 233 sleep 1
 234 echo -e "g\nh\ni" > $follow
 235 sleep 1
 236 kill $child
 237 sleep 1
 238 
 239 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
 240 a=`cat $out`
 241 checktest "$a" "$o" 22
 242 rm $follow
 243 
 244 #
 245 # And truncation with the new offset being greater than the old offset.
 246 #
 247 echo -e "a\nb\nc" > $follow
 248 sleep 1
 249 $PROG -f $follow > $out 2> /dev/null &
 250 child=$!
 251 sleep 2
 252 echo -e "d\ne\nf" >> $follow
 253 sleep 1
 254 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $follow
 255 sleep 1
 256 kill $child
 257 sleep 1
 258 
 259 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
 260 a=`cat $out`
 261 checktest "$a" "$o" 23
 262 rm $follow
 263 
 264 #
 265 # Verify that we can follow the moved file and correctly see a truncation.
 266 #
 267 echo -e "a\nb\nc" > $follow
 268 $PROG -f $follow > $out 2> /dev/null &
 269 child=$!
 270 sleep 2
 271 mv $follow $moved
 272 
 273 echo -e "d\ne\nf" >> $moved
 274 sleep 1
 275 echo -e "g\nh\ni\nj\nk\nl\nm\no\np\nq" > $moved
 276 sleep 1
 277 kill $child
 278 sleep 1
 279 
 280 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\no\np\nq"`
 281 a=`cat $out`
 282 checktest "$a" "$o" 24
 283 rm $moved
 284 
 285 #
 286 # Verify that capital-F follow properly deals with truncation
 287 #
 288 echo -e "a\nb\nc" > $follow
 289 $PROG -F $follow > $out 2> /dev/null &
 290 child=$!
 291 sleep 2
 292 echo -e "d\ne\nf" >> $follow
 293 sleep 1
 294 echo -e "g\nh\ni" > $follow
 295 sleep 1
 296 kill $child
 297 sleep 1
 298 
 299 o=`echo -e "a\nb\nc\nd\ne\nf\ng\nh\ni\n"`
 300 a=`cat $out`
 301 checktest "$a" "$o" 25
 302 rm $follow
 303 
 304 #
 305 # Verify that capital-F follow _won't_ follow the moved file and will
 306 # correctly deal with recreation of the original file.
 307 #
 308 echo -e "a\nb\nc" > $follow
 309 $PROG -F $follow > $out 2> /dev/null &
 310 child=$!
 311 sleep 2
 312 mv $follow $moved
 313 
 314 echo -e "x\ny\nz" >> $moved
 315 echo -e "d\ne\nf" > $follow
 316 sleep 1
 317 kill $child
 318 sleep 1
 319 
 320 o=`echo -e "a\nb\nc\nd\ne\nf\n"`
 321 a=`cat $out`
 322 checktest "$a" "$o" 26
 323 rm $moved
 324 
 325 #
 326 # Verify that following two files works.
 327 #
 328 echo -e "one" > $follow
 329 echo -e "two" > $moved
 330 $PROG -f $follow $moved > $out 2> /dev/null &
 331 child=$!
 332 sleep 2
 333 echo -e "three" >> $follow
 334 sleep 1
 335 echo -e "four" >> $moved
 336 sleep 1
 337 echo -e "five" >> $follow
 338 sleep 1
 339 kill $child
 340 sleep 1
 341 
 342 # There is a bug where the content comes before the header lines,
 343 # where rlines/mapprint happens before the header.  A pain to fix.
 344 # In this test, just make sure we see both files change.
 345 o="one
 346 
 347 ==> $follow <==
 348 two
 349 
 350 ==> $moved <==
 351 
 352 ==> $follow <==
 353 three
 354 
 355 ==> $moved <==
 356 four
 357 
 358 ==> $follow <==
 359 five"
 360 a=`cat $out`
 361 checktest "$a" "$o" 27
 362 rm $follow $moved
 363 
 364 echo "$CMD: completed"
 365 
 366 exit $errs
 367