#!/bin/sh
#
#regression analysis:
#
#1) create directory, file, symlink, hardlink
#   test client, server: -c behavior
#   
#2) modify client and server sides. Test -n behavior.
#
#3) test rsh, ssh transport mechanisms.
#
#4) test message reporting.
#
# test hardlink mismatches
#

test1()
{
echo -n "testing syncing local to remote..."

# create file, directory, link, symlink 
cd $locdir
echo "abcde" > file
chmod 511 file
ln file link
ln file link2
ln -s file symlink
ln -s dangle dsymlink
mkdir dir
echo "fghik" > dir/file

$fsyncprog -c -f $fsyncrc . < /dev/null > $testdir/fsync.log

ok=1
diff $locdir/file $remdir/file || { echo "error in syncing file"; ok=0; }

diff $locdir/dir/file $remdir/dir/file || \
	 { echo "error in syncing dir/file"; ok=0; }
diff $locdir/link $remdir/link || { echo "error in syncing link"; ok=0; }
diff $locdir/link2 $remdir/link2 || { echo "error in syncing link2"; ok=0; }
locsym=`ls -l symlink|cut -d \> -f 2`
remsym=`ls -l $remdir/symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing symlink"
	ok=0
fi

if [ `ls -l $locdir/dsymlink|cut -d \> -f 2` != "dangle" ] ; then
	echo "error in syncing dangling symlink: local"
	ok=0
fi
if [ `ls -l $remdir/dsymlink|cut -d \> -f 2` != "dangle" ] ; then
	echo "error in syncing dangling symlink: remote"
	ok=0
fi
locmod=`ls -l $locdir/file|cut -c -10`
remmod=`ls -l $remdir/file|cut -c -10`
if [ "$locmod" != "$remmod" ] ; then
	echo "error in setting mode"
	ok=0
fi
if [ -e $remdir/exclude ] ; then
	echo "exclude erroneously copied."
	ok=0
fi
[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.

}

test2()
{
prompt=$1
[ "$prompt" = "prompt" ] && echo -n "testing syncing remote to local..."
# create file, directory, link, symlink 

cd $remdir
echo "abcde" > file
echo "don't sync" > exclude
chmod 511 file
ln file link
ln -s file symlink
ln -s dangle dsymlink
mkdir dir
echo "fghik" > dir/file
ln -s ../file dir/symlink


cd $locdir
$fsyncprog -ft -c -f $fsyncrc . dir/symlink </dev/null > /dev/null 
#2>&1

ok=1
diff $locdir/file $remdir/file || { echo "error in syncing file"; ok=0; }
diff $locdir/dir/file $remdir/dir/file || \
	{ echo "error in syncing dir/file"; ok=0; }
diff $locdir/link $remdir/link || { echo "error in syncing link"; ok=0; }
locsym=`ls -l $locdir/symlink|cut -d \> -f 2`
remsym=`ls -l $remdir/symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing symlink"
	ok=0
fi
locsym=`ls -l $locdir/dir/symlink|cut -d \> -f 2`
remsym=`ls -l $remdir/dir/symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing dir/symlink"
	ok=0
fi
locmod=`ls -l $locdir/file|cut -c -10`
remmod=`ls -l $remdir/file|cut -c -10`
if [ "$locmod" != "$remmod" ] ; then
	echo "error in setting mode"
	ok=0
fi
if [ -e $locdir/exclude ] ; then
	echo "exclude erroneously copied."
	ok=0
fi

[ $ok -eq 1 ] && [ "$prompt" = "prompt" ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}

test3()
{
echo -n "testing -n behavior..."

# newer: in comparison with test2:
test2

cd $locdir

rm dsymlink
ln -s dangleNew dsymlink
rm -f file link $remdir/link
newerFileContents="asdpoianwred"
echo $newerFileContents  > file
ln file alink1
#ln file link2

chmod 522 file

newerDirFileContents="fghik"
(
  cd $remdir
  echo $newerDirFileContents > dir/file
  rm dir/symlink
#  echo "blah"  > alink1
  ln -s ../file dir/symlink
)

$fsyncprog -n -S -f $fsyncrc . >& /dev/null

ok=1
diff $locdir/file $remdir/file || { echo "error in syncing file"; ok=0; }
content=`cat $locdir/file`
[ "$content" = "$newerFileContents" ] || \
 { echo "error in syncing file contents: $content != $newerFileContents";
   ok=0; }
diff $locdir/dir/file $remdir/dir/file || \
	{ echo "error in syncing dir/file"; ok=0; }
content=`cat $remdir/dir/file`
[ "$content" = "$newerDirFileContents" ] || \
 { echo "error in syncing file contents: $content != $newerDirFileContents";
   ok=0; }

#diff $locdir/file2 $remdir/file2 || { echo "error in syncing file2"; ok=0; }

#diff $locdir/alink1 $remdir/alink1 || { echo "error in syncing link"; ok=0; }
locsym=`ls -l symlink|cut -d \> -f 2`
remsym=`ls -l symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing symlink"
	ok=0
fi
locmod=`ls -l $locdir/file|cut -c -10`
remmod=`ls -l $remdir/file|cut -c -10`
if [ "$locmod" != "$remmod" ] ; then
	echo "error in setting mode"
	ok=0
fi

if [ `ls -l $locdir/dsymlink|cut -d \> -f 2` != "dangleNew" ] ; then
	echo "error in syncing dangling symlink: local"
	ok=0
fi
if [ `ls -l $remdir/dsymlink|cut -d \> -f 2` != "dangleNew" ] ; then
	echo "error in syncing dangling symlink: remote"
	ok=0
fi

if [ `ls -l $remdir/rem-save/file.0 |cut -d ' ' -f 6` -ne 6 ]; then
    echo "error in creating backup file"
    ok=0
fi

#locmod=`ls -l $locdir/file2|cut -c -10`
#remmod=`ls -l $remdir/file2|cut -c -10`
#if [ "$locmod" != "$remmod" ] ; then
#	 echo "error in setting mode on file2"
#	 ok=0
#fi
[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}

test4()
{
echo -n "testing -c behavior..."
cd $locdir

#  hardlink: both sides have >1 link but one side doesn't include both in 
#  the file list.
echo "zyxw" > $remdir/link2
ln $remdir/link2 $testdir/link2

echo "xyzpdq" > file
ln -s file symlink
mkdir $remdir/dir
echo "pdqxyz" > $remdir/dir/file

#special characters
echo "qwerty" > '<>?"[]{}|\+=-_ !$^%&*()'

$fsyncprog -c -S -f $fsyncrc . > /dev/null

ok=1
diff $locdir/file $remdir/file || { echo "error in syncing file"; ok=0; }
diff $locdir/dir/file $remdir/dir/file || \
	{ echo "error in syncing dir/file"; ok=0; }
#diff $locdir/link $remdir/link || { echo "error in syncing link"; ok=0; }
diff $locdir/link2 $remdir/link2 || { echo "error in syncing link2"; ok=0; }
diff $locdir/'<>?"[]{}|\+=-_ !$^%&*()' $remdir/'<>?"[]{}|\+=-_ !$^%&*()' \
    || { echo "error in syncing "'<>?"[]{}|\+=-_ !$^%&*()'; ok=0; }
locsym=`ls -l symlink|cut -d \> -f 2`
remsym=`ls -l symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing symlink"
	ok=0
fi
locmod=`ls -l $locdir/file|cut -c -10`
remmod=`ls -l $remdir/file|cut -c -10`
if [ "$locmod" != "$remmod" ] ; then
	echo "error in setting mode"
	ok=0
fi
[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}

test5()
{
echo -n "testing -p 0 ..."

cd $locdir

echo "\$rsh = \"rsh REMHOST exec\";	 " >> $fsyncrc

echo abc > file
ln -s file symlink
mkdir dir
echo abcd > dir/file

#  hardlink: both sides have >1 link but one side doesn't include both in 
#  the file list.
echo "zyxw" > $remdir/link2
rm -f $testdir/link2
ln $remdir/link2 $testdir/link2

echo 1 > $locdir/a; chmod 511 $locdir/a
echo 1 > $remdir/b; chmod 511 $remdir/b

echo 12 > $locdir/c; chmod 511 $locdir/c
echo 1  > $remdir/c;  touch -t 200001010101.00 $remdir/c
echo 12 > $remdir/d;  chmod 511 $remdir/d
echo 1  > $locdir/d; touch -t 200001010101.00 $locdir/d

#special characters
echo "qwerty" > '<>?"[]{}|\+=-_ !$^%&*()'


$fsyncprog -p 0 -n -c -S -np -nd -f $fsyncrc . > /dev/null

echo "\$rsh = \"rsh -n REMHOST exec\";	 " >> $fsyncrc

ok=1
diff $locdir/file $remdir/file || { echo "error in syncing file"; ok=0; }
diff $locdir/dir/file $remdir/dir/file || \
	{ echo "error in syncing dir/file"; ok=0; }
#diff $locdir/link $remdir/link || { echo "error in syncing link"; ok=0; }
diff $locdir/link2 $remdir/link2 || { echo "error in syncing link2"; ok=0; }
diff $locdir/'<>?"[]{}|\+=-_ !$^%&*()' $remdir/'<>?"[]{}|\+=-_ !$^%&*()' \
    || { echo "error in syncing "'<>?"[]{}|\+=-_ !$^%&*()'; ok=0; }
locsym=`ls -l symlink|cut -d \> -f 2`
remsym=`ls -l symlink|cut -d \> -f 2`
if [ "$locsym" != "$remsym" ] ; then
	echo "error in syncing symlink"
	ok=0
fi
locmod=`ls -l $locdir/file|cut -c -10`
remmod=`ls -l $remdir/file|cut -c -10`
if [ "$locmod" != "$remmod" ] ; then
	echo "error in setting mode"
	ok=0
fi

amod=`ls -l $remdir/a|cut -c -10`
bmod=`ls -l $locdir/b|cut -c -10`
cmod=`ls -l $remdir/c|cut -c -10`
dmod=`ls -l $locdir/d|cut -c -10`

if [ "$amod" != "-rw-r--r--" ] ; then
	echo "error: changed a mode: $amod"
	ok=0
fi
if [ "$bmod" != "-rw-r--r--" ] ; then
	echo "error: changed b mode: $bmod"
	ok=0
fi
if [ "$cmod" != "-rw-r--r--" ] ; then
	echo "error: changed c mode: $cmod"
	ok=0
fi
if [ "$dmod" != "-rw-r--r--" ] ; then
	echo "error: changed d mode: $dmod"
	ok=0
fi

cdate=`ls -l $remdir/c | sed 's/  */ /g' | cut -d ' ' -f 6-8`
ddate=`ls -l $locdir/d | sed 's/  */ /g' | cut -d ' ' -f 6-8`

if [ "$cdate" != "Jan 1 2000" ] ; then
	echo "error: changed c date: $cdate"
	ok=0
fi
if [ "$ddate" != "Jan 1 2000" ] ; then
	echo "error: changed d date: $ddate"
	ok=0
fi

[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}
test6()
{
echo -n "testing -L ..."


# file
rm -rf $locdir/a
echo 12345 > $locdir/a;   # files differ
rm -rf $remdir/a
echo 2 > $remdir/a;
echo 1 > $remdir/b1;   #file exists remotely but not locally
echo 1 > $locdir/b2;   #file exists locally but not remotely
# make it look like it has been deleted
echo "./b2 972393266 225 3316592770" >$testdir/rem-hash 
echo 1 > $locdir/c1;    #file locally, but dir remotely
rm -rf $remdir/c1
mkdir $remdir/c1
echo 1 > $remdir/c2;    #file remotely, but dir locally
rm -rf $locdir/c2
mkdir $locdir/c2
# make it look like it has been deleted
echo "./c2 972393266 225 3316592770" >>$testdir/rem-hash 
echo 1 > $locdir/d1    #file locally, symlink remotely
rm -rf $remdir/d1
ln -s /bin $remdir/d1
echo 1 > $remdir/d2    #file remotely, symlink locally
rm -rf $locdir/d2
ln -s /bin $locdir/d2

#dir
rm -rf $locdir/e1       #exists locally, not remotely
mkdir $locdir/e1
rm -rf $remdir/e2       #exists remotely, not locally
mkdir $remdir/e2
rm -rf $locdir/f1       #dir locally, symlink remotely
mkdir $locdir/f1
rm -rf $remdir/f1
ln -s /bin $remdir/f1
rm -rf $remdir/f2       #dir remotely, symlink remotely
mkdir $remdir/f2
rm -rf $locdir/f2
ln -s /bin $locdir/f2

rm -rf $locdir/e2.suf    #beginning part of name the same
mkdir $locdir/e2.suf


#symlinks differ
rm -rf $locdir/g
ln -s /etc $locdir/g
rm -rf $remdir/g
ln -s /bin $remdir/g

#hard links
ln $locdir/a $locdir/alink1
ln $locdir/a $locdir/link2
echo "blah1" > $remdir/link2

cd $locdir
$fsyncprog -L -del -f $fsyncrc . > /dev/null

ok=1
if [ `head -1 $locdir/a` != "12345" ]; then
    echo "error in syncing file"
    ok=0
fi
if [ `head -1 $remdir/a` != "12345" ]; then
    echo "error in syncing file"
    ok=0
fi
diff $locdir/a $remdir/a || { echo "diff error in a"; ok=0; }
test -e $remdir/b1 && { echo "b1 exists"; ok=0; }
diff $locdir/b2 $remdir/b2 || { echo "diff error in b2"; ok=0; }
test -f $remdir/c1 || { echo "remdir/c1 is not file"; ok=0; }
diff $locdir/c1 $remdir/c1 || { echo "diff error in c1"; ok=0; }
test -d $locdir/c2 || { echo "locdir/c2 is not file"; ok=0; }
diff $locdir/c2 $remdir/c2 || { echo "diff error in c2"; ok=0; }
test -f $remdir/d1 || { echo "remdir/d1 is not file"; ok=0; }
diff $locdir/d1 $remdir/d1 || { echo "diff error in d1"; ok=0; }
test -L $remdir/d2 || { echo "remdir/d2 is not symlink"; ok=0; }
diff $locdir/d2 $remdir/d2 || { echo "diff error in d2"; ok=0; }

test -d $remdir/e1 || { echo "remdir/e1 is not directory"; ok=0; }
test -e $locdir/e2.suf || { echo "locdir/e2.suf doesn't exist"; ok=0; }
test -e $remdir/e2.suf || { echo "remdir/e2.suf doesn't exist"; ok=0; }
test -e $remdir/e2 && { echo "remdir/e2 exists"; ok=0; }
test -e $locdir/e2 && { echo "locdir/e2 exists"; ok=0; }
test -d $remdir/f1 || { echo "remdir/f1 is not a dir"; ok=0; }
test -L $remdir/f2 || { echo "remdir/f2 is not symlink"; ok=0; }
diff $locdir/f2 $remdir/f2 || { echo "diff error in f2"; ok=0; }
diff $locdir/g $remdir/g || { echo "diff error in g"; ok=0; }

diff $locdir/alink1 $remdir/alink1 || { echo "diff error in alink1"; ok=0; }
diff $locdir/link2 $remdir/link2 || { echo "diff error in link2"; ok=0; }

[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}

test7()
{
echo -n "testing -R ..."


# file XXX
rm -rf $remdir/a
echo 123456 > $remdir/a;   # files differ
rm -rf $locdir/a
echo 2 > $locdir/a;
echo 1 > $locdir/b1;   #file exists remotely but not locally
echo 1 > $remdir/b2;   #file exists locally but not remotely
# make it look like it has been deleted
echo "./b2 972393266 225 3316592770" >$testdir/loc-hash 

echo 1 > $remdir/c1;    #file locally, but dir remotely
rm -rf $locdir/c1
mkdir $locdir/c1
rm -rf $locdir/c2
echo 1 > $locdir/c2;    #file remotely, but dir locally
rm -rf $remdir/c2
mkdir $remdir/c2
# make it look like it has been deleted
echo "./c2 972393266 225 3316592770" >>$testdir/loc-hash 
echo 1 > $remdir/d1    #file locally, symlink remotely
rm -rf $locdir/d1
ln -s /bin $locdir/d1
rm -rf $locdir/d2
echo 1 > $locdir/d2    #file remotely, symlink locally
rm -rf $remdir/d2
ln -s /bin $remdir/d2

#dir
rm -rf $remdir/e1       #exists locally, not remotely
mkdir $remdir/e1
rm -rf $locdir/e2       #exists remotely, not locally
mkdir $locdir/e2
rm -rf $remdir/f1       #dir locally, symlink remotely
mkdir $remdir/f1
rm -rf $locdir/f1
ln -s /bin $locdir/f1
rm -rf $locdir/f2       #dir remotely, symlink remotely
mkdir $locdir/f2
rm -rf $remdir/f2
ln -s /bin $remdir/f2

#symlinks differ
rm -rf $remdir/g
ln -s /etc $remdir/g
rm -rf $locdir/g
ln -s /bin $locdir/g

#hardlink
rm -rf $locdir/h
rm -rf $remdir/h
ln $locdir/a $remdir/h
ln $locdir/b1 $locdir/h

cd $locdir

$fsyncprog -R -del -f $fsyncrc . >> $testdir/fsync.log

ok=1
if [ `head -1 $remdir/a` != "123456" ]; then
    echo "error in syncing file"
    ok=0
fi
if [ `head -1 $locdir/a` != "123456" ]; then
    echo "error in syncing file"
    ok=0
fi
diff $remdir/a $locdir/a || { echo "diff error in a";ok=0; }
test -e $locdir/b1 && { echo "b1 exists"; ok=0; }
diff $remdir/b2 $locdir/b2 || { echo "diff error in b2"; ok=0; }
test -f $locdir/c1 || { echo "locdir/c1 is not file"; ok=0; }
diff $remdir/c1 $locdir/c1 || { echo "diff error in c1"; ok=0; }
test -d $remdir/c2 || { echo "remdir/c2 is not file"; ok=0; }
diff $remdir/c2 $locdir/c2 || { echo "diff error in c2"; ok=0; }
test -f $locdir/d1 || { echo "locdir/d1 is not file"; ok=0; }
diff $remdir/d1 $locdir/d1 || { echo "diff error in d1"; ok=0; }
test -L $locdir/d2 || { echo "locdir/d2 is not symlink"; ok=0; }
diff $remdir/d2 $locdir/d2 || { echo "diff error in d2"; ok=0; }

test -d $locdir/e1 || { echo "locdir/e1 is not directory"; ok=0; }
test -e $locdir/e2 && { echo "locdir/e2 exists"; ok=0; }
test -e $remdir/e2 && { echo "remdir/e2 exists"; ok=0; }
test -d $locdir/f1 || { echo "locdir/f1 is not a dir"; ok=0; }
test -L $locdir/f2 || { echo "locdir/f2 is not symlink"; ok=0; }
diff $remdir/f2 $locdir/f2 || { echo "diff error in f2"; ok=0; }
diff $remdir/g $locdir/g || { echo "diff error in g"; ok=0; }
diff $remdir/h $locdir/h || { echo "diff error in h"; ok=0; }

[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}

test8()
{
echo -n "testing -c -del behavior..."
ok=1
cd $locdir

# make local directory, sync
#
mkdir deletedDir
mkdir $remdir/deletedDir2

$fsyncprog -del -c -S -f $fsyncrc . > /dev/null

# remove directories, resync
#
rmdir deletedDir
rmdir $remdir/deletedDir2
$fsyncprog -del -c -S -f $fsyncrc . > /dev/null

#local and remote directories should be gone.
if [ -d $locdir/deletedDir ]; then
    echo "error: directory recreated locally."
    ok=0
fi
if [ -d $remdir/deletedDir ]; then
    echo "error: directory not deleted remotely."
    ok=0
fi
if [ -d $locdir/deletedDir2 ]; then
    echo "error: directory recreated remotely."
    ok=0
fi
if [ -d $remdir/deletedDir2 ]; then
    echo "error: directory not deleted locally."
    ok=0
fi

[ $ok -eq 1 ] && echo ok.
[ $ok -eq 0 ] && echo FAILED.
}


#
# parse command line
#
verbose=0
if [  "$1" = "-v" ] ; then 
    echo "running verbose"
    verbose=9
    shift
fi
tests=""
while [  $# -ge 1 ]; do
    tests="$tests $1"
    shift
done
[ "$tests" = "" ]  && tests="1 2 3 4 5 6 7 8"
echo "performing the following tests: $tests"

#
# initialize
#

# allow rsh access
echo "localhost $USER" cat - $HOME/.rhosts > $HOME/.rhosts

umask 22
testdir=/tmp/fsync-test
locdir=$testdir/local/
remdir=$testdir/remote/
fsyncrc=$testdir/fsyncrc
fsyncprog="perl -w `pwd`/fsync"

mkdir $testdir
echo > $fsyncrc 
echo "\$verbose = $verbose;              " >> $fsyncrc
echo "\$remhost = \"localhost\";	 " >> $fsyncrc
echo "\$rsh = \"rsh -n REMHOST exec\";	 " >> $fsyncrc
echo "\$port = 9006;			 " >> $fsyncrc
echo "\$Slogfile = \"$testdir/fsyncd.log\";	 " >> $fsyncrc
echo "\$progname = \"$fsyncprog\";       " >> $fsyncrc
echo "\$backupDir     = \"loc-save\";    " >> $fsyncrc
echo "\$rBackupDir    = \"rem-save\";    " >> $fsyncrc
echo "\$hashSaveFile  = \"$testdir/loc-hash\";    " >> $fsyncrc
echo "\$rHashSaveFile = \"$testdir/rem-hash\";    " >> $fsyncrc
echo "\$rootdir       = \"$locdir\";     " >> $fsyncrc
echo "\$rem_rootdir   = \"$remdir\";     " >> $fsyncrc
echo '$dbBlockSize=2;'                     >> $fsyncrc
echo 'push(@excludeList, "exclude");'      >> $fsyncrc


#
# run tests
#

for d in $tests; do
    rm -rf $locdir $remdir
    mkdir -p $locdir $remdir
    echo -n "test $d: "
    test$d prompt
done

#
# clean up
#

# remove rsh access
tail +2 $HOME/.rhosts > $HOME/.rhosts

if [ $verbose -eq 0 ]; then
    cd /tmp
    rm -rf $testdir
fi
