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