1#!/bin/sh 2# 3# cmptest @(#)cmptest.sh 1.15 20/08/25 Copyright 2015-2020 J. Schilling 4# 5# Usage: cmptest ---> runs 1000 test loops 6# cmptest # ---> runs # test loops 7# 8# A random file test with patch -DXXX usage. 9# A file is generated, then modified. 10# Then a patch file is created from original and new file. 11# A reference patch implementation is called with -DXXX and the output 12# is compared to the output from out test patch. Gpatch is buggy, so we 13# sometimes need to use our test patch as reference. 14# 15# Finally cpp is used to check whether original and new file can be 16# reconstructed from the #ifdef XXX ... #else ... #endif parts. 17# 18# The diff type is random, this allows to check all diff types. 19# 20 21[ "$NO_RANDOM" = TRUE ] && exit 22 23: ${AWK=/usr/bin/nawk} 24#$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=/usr/bin/nawk 25$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=/usr/bin/gawk 26$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=/usr/bin/awk 27$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=nawk 28$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=gawk 29$AWK 'BEGIN {print rand()}' < /dev/null > /dev/null 2> /dev/null || AWK=awk 30 31: ${CPP=/lib/cpp} 32$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/usr/lib/cpp 33$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/usr/ccs/lib/cpp 34$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/usr/bin/cpp 35$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/bin/cpp 36$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/opt/schily/lib/cpp 37$CPP < /dev/null > /dev/null 2> /dev/null || CPP=../../../cpp/OBJ/"`../../../conf/oarch.sh`"/cpp 38$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/usr/sfw/bin/cpp 39$CPP < /dev/null > /dev/null 2> /dev/null || CPP=/usr/gnu/bin/cpp 40$CPP < /dev/null > /dev/null 2> /dev/null || CPP=cpp 41 42trap 'cleanup; exit' EXIT INT HUP 43 44cleanup() { 45 rm -f saved_orig changed patch_file expected original original.* failure xo xm xof xmf xef 46} 47 48rrand() { 49 $AWK ' 50 function random(low, range) { 51 return int(range * rand()) + low 52 } 53 54 BEGIN { 55 base = ARGV[1] 56 max = ARGV[2] 57 seed = ARGV[3] 58 59 srand() # Initialze with current time 60 s = srand() # get previous seed 61 s = s + seed # Current time + seed 62 srand(s) # Better new seed 63 64 x = random(base, max) 65 print x 66 } 67 ' "$@" 68} 69 70makefile() { 71 $AWK ' 72 BEGIN { 73 nflines = ARGV[1] 74 for (i = 1; i <= nflines; i++) { 75 printf("This is original line %d\n", i); 76 } 77 } 78 ' "$@" 79} 80 81changefile() { 82 $AWK ' 83 function random(n) { 84 return int(n * rand()) 85 } 86 87 BEGIN { 88 nflines = ARGV[1] 89 chlines = ARGV[2] 90 seed = chlines 91 92 ARGV[1] = "" # Do not use as filename 93 ARGV[2] = "" # Do not use as filename 94 95 srand() # Initialze with current time 96 s = srand() # get previous seed 97 s = s + seed # Current time + seed 98 srand(s) # Better new seed 99 100 for (i = 1; i <= nflines; i++) { 101 change_line[i] = 0 102 } 103 104 while (chlines > 0) { 105 i = random(nflines) 106 if (change_line[i] == 0) { 107 chlines-- 108 change_line[i] = 1 109 } 110 } 111 i = 1; 112 } 113 114 { 115 if (change_line[i] != 0) { 116 what = random(3) 117 if (what == 0) { 118 print "Modified, was: " $0 119 } else if (what == 1) { 120 print $0 121 print "New line, inserted after: " $0 122 } 123 } else { 124 print $0 125 } 126 i++ 127 next 128 } 129 ' "$@" 130} 131 132nlines=$$ # seed startup helper, awk would get seed based on time_t 133maxlines=5000 # Longest file for our tests 134maxch=4 # Max. 25% of all lines are changed 135 136# 137# Diff Program to use. Solaris diff -U0 has bugs, so use our fixed Solaris diff 138# from the SCCS distribution. 139# 140is_bdiff=false 141: ${diff=/opt/schily/ccs/bin/diff} 142type $diff > /dev/null 2> /dev/null 143[ $? -ne 0 ] && diff=diff # fallback to probably defective system diff 144LC_ALL=C $diff -? 2>&1 | grep -i Option > /dev/null 145if [ $? -ne 0 ]; then 146 LC_ALL=C $diff -? 2>&1 | grep -i "bdiff: arg count" > /dev/null 147 if [ $? -eq 0 ]; then 148 is_bdiff=true 149 else 150 echo "No working diff program found" 151 exit 1 152 fi 153fi 154echo "Using diff programm: $diff" 155# 156# Reference patch program, note that gpatch has problems itself 157# and fails with -diff -C0 158# 159rpatch=gpatch 160LC_ALL=C $rpatch -? 2>&1 | grep -i Option > /dev/null 161if [ $? -ne 0 ]; then 162 echo "Reference patch program \"$rpatch\" not working" 163 rpatch=/usr/bin/patch 164 echo "Trying \"$rpatch\"..." 165 LC_ALL=C $rpatch -? 2>&1 | grep -i Option > /dev/null 166 if [ $? -ne 0 ]; then 167 echo "Reference patch program \"$rpatch\" not working" 168 rpatch=/bin/patch 169 echo "Trying \"$rpatch\"..." 170 LC_ALL=C $rpatch -? 2>&1 | grep -i Option > /dev/null 171 if [ $? -ne 0 ]; then 172 echo "Reference patch program \"$rpatch\" not working" 173 exit 1 174 fi 175 fi 176fi 177echo "Using reference patch programm: $rpatch" 178# 179# Test patch implementation: 180# Add -W+ to permit POSIX + enhancements for "patch -s" 181# 182tpatch="eval ../../OBJ/"`../../../conf/oarch.sh`"/spatch -W+" 183silent=-s 184LC_ALL=C $tpatch -? 2>&1 | grep -i Option > /dev/null 185if [ $? -ne 0 ]; then 186 echo "Test patch program \"$tpatch\" not working" 187 exit 1 188fi 189echo "Using test patch programm: $tpatch" 190 191mod=6 192type ed > /dev/null 2> /dev/null 193[ $? -ne 0 ] && mod=5 # Skip diff -e tests 194if [ $mod = 5 ]; then 195 echo "No ed program found, skipping diff -e tests" 196fi 197 198idx=0 199maxidx=${1:-1000} 200while [ $idx -le $maxidx ] 201do 202 nlines=`rrand 10 $maxlines $nlines` 203 204 max_changes=`expr $nlines / $maxch` 205 changes=`rrand 1 $max_changes $nlines` 206 207 makefile $nlines > original 208 cp original saved_orig 209 210 echo Test $idx: testing nlines=$nlines changes=$changes 211 212 dtype=`rrand 0 93983 $nlines` # rrand 0 6 would be of bad quality, so 213 dtype=`expr $dtype \% $mod` # use "rrand 0 bigprime % 6" instead 214 215 if [ $dtype -eq 0 ]; then 216 dtype="-c" 217 elif [ $dtype -eq 1 ]; then 218 dtype="-u" 219 elif [ $dtype -eq 2 ]; then 220 dtype="-C0" 221 elif [ $dtype -eq 3 ]; then 222 dtype="-U0" 223 elif [ $dtype -eq 5 ]; then 224 dtype="-e" 225 else 226 dtype=" " 227 fi 228 if [ "$is_bdiff" = true ]; then 229 dtype=" " 230 fi 231 232 changefile $nlines $changes original > changed 233 echo diff $dtype original changed 234 echo "Index:original" > patch_file 235 $diff $dtype original changed >> patch_file 236 237 cp saved_orig original 238 # 239 # $rpatch: gpatch is buggy and does not support "diff -C0" 240 # If the reference patch program fails (exit != 0), we use out test patch 241 # 242 $rpatch -D XXX original < patch_file || \ 243 ( echo "Reference patch program \"$rpatch\" failed, using test patch \"$tpatch\""; \ 244 $tpatch $silent -D XXX original < patch_file) 245 # 246 # gpatch never uses "#endif /* XXX */", 247 # FreeBSD patch always adds " /* XXX */", so we need to remove it. 248 # Our patch # depends on wether it is in POSIX mode, where the comment is missing 249 # 250## sed -e 's^#endif$^#endif /* XXX */^g' < original > expected 251# cp original expected 252 sed -e 's^#endif /\* XXX \*/$^#endif^g' < original > expected 253 254 if [ "$dtype" = "-e" ]; then 255 diff changed original > xef 256 ret=$? 257 if [ $ret -ne 0 ]; then 258 echo Test $idx: Reference Patch $dtype did not restore original 259 if test `uname` = FreeBSD; then 260 # 261 # /usr/bin/patch from FreeBSD is buggy. 262 # Pretend it works by copying the right file content. 263 # 264 cp changed expected 265 else 266 [ $ret -eq 1 ] && trap 0 267 exit 1 268 fi 269 fi 270 else 271 $CPP original | grep This > xo 272 $CPP -DXXX original | grep This > xm 273 diff saved_orig xo > xof 274 ret=$? 275 if [ $ret -ne 0 ]; then 276 echo Test $idx: Reference Patch $dtype did not restore original 277 [ $ret -eq 1 ] && trap 0 278 exit 1 279 fi 280 diff changed xm > xmf 281 ret=$? 282 if [ $ret -ne 0 ]; then 283 echo Test $idx: Reference Patch $dtype did not restore changed 284 [ $ret -eq 1 ] && trap 0 285 exit 1 286 fi 287 fi 288 289 290 echo Patching file... 291 cp saved_orig original 292 $tpatch $silent -D XXX original < patch_file 293 ret=$? 294 if [ $ret -ne 0 ]; then 295 echo Test $idx: Patch $dtype returned $ret 296 diff original expected > failure 297 trap 0 298 exit 1 299 fi 300 301 diff original expected > failure 302 ret=$? 303 if [ $ret -ne 0 ]; then 304 echo Test $idx: diff $dtype returned $ret 305 [ $ret -eq 1 ] && trap 0 306 exit 1 307 fi 308 idx=`expr $idx + 1` 309done 310idx=`expr $idx - 1` 311echo Test succeeded after $idx runs... 312