1 #!/bin/bash 2 # 3 # A test suite for applypatch. Run in a client where you have done 4 # envsetup, choosecombo, etc. 5 # 6 # DO NOT RUN THIS ON A DEVICE YOU CARE ABOUT. It will mess up your 7 # system partition. 8 # 9 # 10 # TODO: find some way to get this run regularly along with the rest of 11 # the tests. 12 13 EMULATOR_PORT=5580 14 DATA_DIR=$ANDROID_BUILD_TOP/bootable/recovery/applypatch/testdata 15 16 # This must be the filename that applypatch uses for its copies. 17 CACHE_TEMP_SOURCE=/cache/saved.file 18 19 # Put all binaries and files here. We use /cache because it's a 20 # temporary filesystem in the emulator; it's created fresh each time 21 # the emulator starts. 22 WORK_DIR=/system 23 24 # partition that WORK_DIR is located on, without the leading slash 25 WORK_FS=system 26 27 # set to 0 to use a device instead 28 USE_EMULATOR=1 29 30 # ------------------------ 31 32 tmpdir=$(mktemp -d) 33 34 if [ "$USE_EMULATOR" == 1 ]; then 35 emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT & 36 pid_emulator=$! 37 ADB="adb -s emulator-$EMULATOR_PORT " 38 else 39 ADB="adb -d " 40 fi 41 42 echo "waiting to connect to device" 43 $ADB wait-for-device 44 echo "device is available" 45 $ADB remount 46 # free up enough space on the system partition for the test to run. 47 $ADB shell rm -r /system/media 48 49 # run a command on the device; exit with the exit status of the device 50 # command. 51 run_command() { 52 $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}' 53 } 54 55 testname() { 56 echo 57 echo "$1"... 58 testname="$1" 59 } 60 61 fail() { 62 echo 63 echo FAIL: $testname 64 echo 65 [ "$open_pid" == "" ] || kill $open_pid 66 [ "$pid_emulator" == "" ] || kill $pid_emulator 67 exit 1 68 } 69 70 sha1() { 71 sha1sum $1 | awk '{print $1}' 72 } 73 74 free_space() { 75 run_command df | awk "/$1/ {print gensub(/K/, \"\", \"g\", \$6)}" 76 } 77 78 cleanup() { 79 # not necessary if we're about to kill the emulator, but nice for 80 # running on real devices or already-running emulators. 81 testname "removing test files" 82 run_command rm $WORK_DIR/bloat.dat 83 run_command rm $WORK_DIR/old.file 84 run_command rm $WORK_DIR/foo 85 run_command rm $WORK_DIR/patch.bsdiff 86 run_command rm $WORK_DIR/applypatch 87 run_command rm $CACHE_TEMP_SOURCE 88 run_command rm /cache/bloat*.dat 89 90 [ "$pid_emulator" == "" ] || kill $pid_emulator 91 92 if [ $# == 0 ]; then 93 rm -rf $tmpdir 94 fi 95 } 96 97 cleanup leave_tmp 98 99 $ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch 100 101 BAD1_SHA1=$(printf "%040x" $RANDOM) 102 BAD2_SHA1=$(printf "%040x" $RANDOM) 103 OLD_SHA1=$(sha1 $DATA_DIR/old.file) 104 NEW_SHA1=$(sha1 $DATA_DIR/new.file) 105 NEW_SIZE=$(stat -c %s $DATA_DIR/new.file) 106 107 # --------------- basic execution ---------------------- 108 109 testname "usage message" 110 run_command $WORK_DIR/applypatch && fail 111 112 testname "display license" 113 run_command $WORK_DIR/applypatch -l | grep -q -i copyright || fail 114 115 116 # --------------- check mode ---------------------- 117 118 $ADB push $DATA_DIR/old.file $WORK_DIR 119 120 testname "check mode single" 121 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail 122 123 testname "check mode multiple" 124 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail 125 126 testname "check mode failure" 127 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail 128 129 $ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE 130 # put some junk in the old file 131 run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail 132 133 testname "check mode cache (corrupted) single" 134 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail 135 136 testname "check mode cache (corrupted) multiple" 137 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail 138 139 testname "check mode cache (corrupted) failure" 140 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail 141 142 # remove the old file entirely 143 run_command rm $WORK_DIR/old.file 144 145 testname "check mode cache (missing) single" 146 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail 147 148 testname "check mode cache (missing) multiple" 149 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail 150 151 testname "check mode cache (missing) failure" 152 run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail 153 154 155 # --------------- apply patch ---------------------- 156 157 $ADB push $DATA_DIR/old.file $WORK_DIR 158 $ADB push $DATA_DIR/patch.bsdiff $WORK_DIR 159 echo hello > $tmpdir/foo 160 $ADB push $tmpdir/foo $WORK_DIR 161 162 # Check that the partition has enough space to apply the patch without 163 # copying. If it doesn't, we'll be testing the low-space condition 164 # when we intend to test the not-low-space condition. 165 testname "apply patches (with enough space)" 166 free_kb=$(free_space $WORK_FS) 167 echo "${free_kb}kb free on /$WORK_FS." 168 if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then 169 echo "Not enough space on /$WORK_FS to patch test file." 170 echo 171 echo "This doesn't mean that applypatch is necessarily broken;" 172 echo "just that /$WORK_FS doesn't have enough free space to" 173 echo "properly run this test." 174 exit 1 175 fi 176 177 testname "apply bsdiff patch" 178 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 179 $ADB pull $WORK_DIR/old.file $tmpdir/patched 180 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 181 182 testname "reapply bsdiff patch" 183 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 184 $ADB pull $WORK_DIR/old.file $tmpdir/patched 185 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 186 187 188 # --------------- apply patch in new location ---------------------- 189 190 $ADB push $DATA_DIR/old.file $WORK_DIR 191 $ADB push $DATA_DIR/patch.bsdiff $WORK_DIR 192 193 # Check that the partition has enough space to apply the patch without 194 # copying. If it doesn't, we'll be testing the low-space condition 195 # when we intend to test the not-low-space condition. 196 testname "apply patch to new location (with enough space)" 197 free_kb=$(free_space $WORK_FS) 198 echo "${free_kb}kb free on /$WORK_FS." 199 if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then 200 echo "Not enough space on /$WORK_FS to patch test file." 201 echo 202 echo "This doesn't mean that applypatch is necessarily broken;" 203 echo "just that /$WORK_FS doesn't have enough free space to" 204 echo "properly run this test." 205 exit 1 206 fi 207 208 run_command rm $WORK_DIR/new.file 209 run_command rm $CACHE_TEMP_SOURCE 210 211 testname "apply bsdiff patch to new location" 212 run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 213 $ADB pull $WORK_DIR/new.file $tmpdir/patched 214 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 215 216 testname "reapply bsdiff patch to new location" 217 run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 218 $ADB pull $WORK_DIR/new.file $tmpdir/patched 219 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 220 221 $ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE 222 # put some junk in the old file 223 run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail 224 225 testname "apply bsdiff patch to new location with corrupted source" 226 run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo || fail 227 $ADB pull $WORK_DIR/new.file $tmpdir/patched 228 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 229 230 # put some junk in the cache copy, too 231 run_command dd if=/dev/urandom of=$CACHE_TEMP_SOURCE count=100 bs=1024 || fail 232 233 run_command rm $WORK_DIR/new.file 234 testname "apply bsdiff patch to new location with corrupted source and copy (no new file)" 235 run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail 236 237 # put some junk in the new file 238 run_command dd if=/dev/urandom of=$WORK_DIR/new.file count=100 bs=1024 || fail 239 240 testname "apply bsdiff patch to new location with corrupted source and copy (bad new file)" 241 run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail 242 243 # --------------- apply patch with low space on /system ---------------------- 244 245 $ADB push $DATA_DIR/old.file $WORK_DIR 246 $ADB push $DATA_DIR/patch.bsdiff $WORK_DIR 247 248 free_kb=$(free_space $WORK_FS) 249 echo "${free_kb}kb free on /$WORK_FS; we'll soon fix that." 250 echo run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail 251 run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail 252 free_kb=$(free_space $WORK_FS) 253 echo "${free_kb}kb free on /$WORK_FS now." 254 255 testname "apply bsdiff patch with low space" 256 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 257 $ADB pull $WORK_DIR/old.file $tmpdir/patched 258 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 259 260 testname "reapply bsdiff patch with low space" 261 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 262 $ADB pull $WORK_DIR/old.file $tmpdir/patched 263 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 264 265 # --------------- apply patch with low space on /system and /cache ---------------------- 266 267 $ADB push $DATA_DIR/old.file $WORK_DIR 268 $ADB push $DATA_DIR/patch.bsdiff $WORK_DIR 269 270 free_kb=$(free_space $WORK_FS) 271 echo "${free_kb}kb free on /$WORK_FS" 272 273 run_command mkdir /cache/subdir 274 run_command 'echo > /cache/subdir/a.file' 275 run_command 'echo > /cache/a.file' 276 run_command mkdir /cache/recovery /cache/recovery/otatest 277 run_command 'echo > /cache/recovery/otatest/b.file' 278 run_command "echo > $CACHE_TEMP_SOURCE" 279 free_kb=$(free_space cache) 280 echo "${free_kb}kb free on /cache; we'll soon fix that." 281 run_command dd if=/dev/zero of=/cache/bloat_small.dat count=128 bs=1024 || fail 282 run_command dd if=/dev/zero of=/cache/bloat_large.dat count=$((free_kb-640)) bs=1024 || fail 283 free_kb=$(free_space cache) 284 echo "${free_kb}kb free on /cache now." 285 286 testname "apply bsdiff patch with low space, full cache, can't delete enough" 287 $ADB shell 'cat >> /cache/bloat_large.dat' & open_pid=$! 288 echo "open_pid is $open_pid" 289 290 # size check should fail even though it deletes some stuff 291 run_command $WORK_DIR/applypatch -s $NEW_SIZE && fail 292 run_command ls /cache/bloat_small.dat && fail # was deleted 293 run_command ls /cache/a.file && fail # was deleted 294 run_command ls /cache/recovery/otatest/b.file && fail # was deleted 295 run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open 296 run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir 297 run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy 298 299 # should fail; not enough files can be deleted 300 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff && fail 301 run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open 302 run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir 303 run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy 304 305 kill $open_pid # /cache/bloat_large.dat is no longer open 306 307 testname "apply bsdiff patch with low space, full cache, can delete enough" 308 309 # should succeed after deleting /cache/bloat_large.dat 310 run_command $WORK_DIR/applypatch -s $NEW_SIZE || fail 311 run_command ls /cache/bloat_large.dat && fail # was deleted 312 run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir 313 run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy 314 315 # should succeed 316 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 317 $ADB pull $WORK_DIR/old.file $tmpdir/patched 318 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 319 run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir 320 run_command ls $CACHE_TEMP_SOURCE && fail # was deleted because patching overwrote it, then deleted it 321 322 # --------------- apply patch from cache ---------------------- 323 324 $ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE 325 # put some junk in the old file 326 run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail 327 328 testname "apply bsdiff patch from cache (corrupted source) with low space" 329 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 330 $ADB pull $WORK_DIR/old.file $tmpdir/patched 331 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 332 333 $ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE 334 # remove the old file entirely 335 run_command rm $WORK_DIR/old.file 336 337 testname "apply bsdiff patch from cache (missing source) with low space" 338 run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail 339 $ADB pull $WORK_DIR/old.file $tmpdir/patched 340 diff -q $DATA_DIR/new.file $tmpdir/patched || fail 341 342 343 # --------------- cleanup ---------------------- 344 345 cleanup 346 347 echo 348 echo PASS 349 echo 350 351