Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 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 |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 14 | DATA_DIR=$ANDROID_BUILD_TOP/bootable/recovery/applypatch/testdata |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 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 |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 84 | run_command rm $WORK_DIR/foo |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 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 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 92 | if [ $# == 0 ]; then |
| 93 | rm -rf $tmpdir |
| 94 | fi |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 95 | } |
| 96 | |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 97 | cleanup leave_tmp |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 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 |
Doug Zongker | c4351c7 | 2010-02-22 14:46:32 -0800 | [diff] [blame] | 159 | echo hello > $tmpdir/foo |
| 160 | $ADB push $tmpdir/foo $WORK_DIR |
Doug Zongker | 512536a | 2010-02-17 16:11:44 -0800 | [diff] [blame] | 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 | |