The new algorithms pass all but one subtest of the existing diff tests. This
one I have forced to stone, I think this is okay as it very recent
functionality.
Due to different diff algorithms generating different, but equivalent diffs we
have to verify functionality by running each an ensuring that applying the
created diff with patch creates the same file.
The following test file runs through commits passed on the command line and
checks that the diff remains valid between unpatched diff, gdiff and the
updated diff. I have used this for testing and it is happy with the most recent
1000 FreeBSD commits.
'''
#!/bin/sh
#
# Test diff command by running through the commits in a git repository that is
# the current working directory. Test is performed by taking each commit and
# checking if it is equivalent (patched file is the same) as installed diff,
# gdiff and the git diff output. test-commit.sh uses $testdiffcmd and tries to
# only log minimal progress and errors.
testdiffcmd=/usr/obj/code/freebsd/worktrees/diff-got/amd64.amd64/usr.bin/diff/diff.full
#
#
# Takes commits to test on the command line
# $ test-commit.sh 57f7a82fbb4299a255c2c20ec812258004a90631 7d98cc096b995ca3bfd85277ed009b0f872c3e1b ...
#
# failed diffs end up in test-commit.log
#
# To get big lists of commits to test we can use git log and xargs, Run through
# many commits as generated by git in 100 commit chunks increasing -P adds more
# jobs, but there seem to be concurrency issues:
# git log -n 1000 --pretty=format:"%H" | xargs -P1 -L 100 -t sh ./test-commit.sh unified
# will run through 1000 commits, in 100 commit chunks, with one thread
#
# Testing files are named to try and allow concurrent access to the git repo
# for tests.
mode=$1
shift
case $mode in
"classic")
diffflags=""
patchflags="-s -n"
;;
"ed")
diffflags="-e"
patchflags="-e"
;;
"unified")
diffflags="-u"
patchflags="-s -u"
;;
"func")
diffflags="-u -p"
patchflags="-s -u"
;;
*)
echo "no valid mode specified"
echo "usage: test-commit.sh [classic | ed | unified ] hash hash hash ..."
exit
;;
esac
commits=$@
if [ -z "$commits" ]
then
echo no commits specified
exit
fi
outdir=testdir
logfile=test-commit.log
patchcmd=gpatch
commitcount=0
filecount=0
skipcount=0
for commit in $commits
do
commitcount=$((commitcount+1))
prevcommit=$(git log -n 1 --pretty=format:"%H" $commit^1)
files=$(git diff --name-only $prevcommit $commit)
if [ -z $prevcommit ]
then
echo "no previous commits for $commit"
continue
fi
printf "$commitcount: $commit -> $prevcommit\n\t"
for f in $files
do
printf "."
filecount=$((filecount+1))
filename=$(basename $f)
afile=${outdir}/${filename}-${prevcommit}-a
bfile=${outdir}/${filename}-${commit}-b
gitdiff=${outdir}/gitdiff-${prevcommit}-${commit}
gdiff=${outdir}/gdiff-${prevcommit}-${commit}
bsddiff=${outdir}/bsddiff-${prevcommit}-${commit}
testdiff=${outdir}/testdiff-${prevcommit}-${commit}
gitpatch=${outdir}/gitpatch-${prevcommit}-${commit}
gdiffpatch=${outdir}/gdiffpatch-${prevcommit}-${commit}
bsdpatch=${outdir}/bsdpatch-${prevcommit}-${commit}
testdiffpatch=${outdir}/testdiffpatch-${prevcommit}-${commit}
git --no-pager show ${prevcommit}:${f} 2>/dev/null > $afile
if [ $? -ne 0 ]
then
#echo "no a file skipping $f"
skipcount=$((skipcount+1))
continue
fi
git --no-pager show ${commit}:${f} 2>/dev/null > $bfile
if [ $? -ne 0 ]
then
#echo "no b file skipping $f"
skipcount=$((skipcount+1))
continue
fi
cp ${afile} ${gitpatch}
cp ${afile} ${gdiffpatch}
cp ${afile} ${bsdpatch}
git diff ${prevcommit}:${f} ${commit}:${f} > ${gitdiff}
gdiff ${diffflags} $afile $bfile > ${gdiff}
diff ${diffflags} $afile $bfile > ${bsddiff}
# Check that the git patch creates b file
$patchcmd -s -u ${gitpatch} ${gitdiff}
if [ $? -gt 1 ]
then
echo "patch failed skipping $f"
skipcount=$((skipcount+1))
continue
fi
cmp ${bfile} ${gitpatch}
# Check that the bsddiff (stone) patch creates b file
$patchcmd ${patchflags} ${bsdpatch} ${bsddiff}
cmp ${bfile} ${bsdpatch}
if [ $? -ne 0 ]
then
# if the first test failed, this might be a binary. If
# it is skip this file
if ! file --mime $f | grep -q "text"
then
file --mime $f | grep -q "text"
echo "binary file skipping $f"
skipcount=$((skipcount+1))
continue
fi
fi
# Check that the gdiff patch creates b file
$patchcmd ${patchflags} ${gdiffpatch} ${gdiff}
cmp ${bfile} ${gdiffpatch}
#diffstat < ${gitdiff}
#wc -l ${afile} ${bfile}
if [ ! -z $testdiffcmd ]
then
#echo "running: $testdiffcmd ${diffflags} $afile $bfile > ${testdiff}"
$testdiffcmd -A myers ${diffflags} $afile $bfile > ${testdiff}
cp ${afile} ${testdiffpatch}
$patchcmd ${patchflags} ${testdiffpatch} ${testdiff}
cmp ${bfile} ${testdiffpatch}
if [ $? -ne 0 ]
then
echo failed $prevcommit $commit >> ${logfile}
echo $(tput bold) test diff failed $(tput sgr0)
echo diff ${diffflags} ${afile} ${bfile}
echo "processed $filecount files from $commitcount commits (skipped $skipcount)"
exit 255
fi
fi
done
printf "\n"
done
#echo "Sucessfully diffed $filecount files from $commitcount commits (skipped $skipcount)"
#echo "$commits" | wc -l
#commitbacklog=100
#commits=$(git log -n ${commitbacklog} --pretty=format:"%H")
# rm log.out; time git log -n 1000 --pretty=format:"%H" | xargs -P4 -L 100 -t sh ./test-commit.sh
'''