blob: 193e7fdee092b8172057280ff938cfa0a3d88e02 [file] [log] [blame]
The Android Open Source Project66339ad2009-01-15 16:12:07 -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# ------------------------
28
29tmpdir=$(mktemp -d)
30
31emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
32pid_emulator=$!
33
34ADB="adb -s emulator-$EMULATOR_PORT "
35
36echo "emulator is $pid_emulator; waiting for startup"
37$ADB wait-for-device
38echo "device is available"
39$ADB remount
40# free up enough space on the system partition for the test to run.
41$ADB shell rm -r /system/media
42
43# run a command on the device; exit with the exit status of the device
44# command.
45run_command() {
46 $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
47}
48
49testname() {
50 echo
51 echo "$1"...
52 testname="$1"
53}
54
55fail() {
56 echo
57 echo FAIL: $testname
58 echo
59 kill $pid_emulator
60 exit 1
61}
62
63sha1() {
64 sha1sum $1 | awk '{print $1}'
65}
66
67free_space() {
68 run_command df | awk "/$1/ {print gensub(/K/, \"\", \"g\", \$6)}"
69}
70
71
72$ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch
73
74BAD1_SHA1=$(printf "%040x" $RANDOM)
75BAD2_SHA1=$(printf "%040x" $RANDOM)
76OLD_SHA1=$(sha1 $DATA_DIR/old.file)
77NEW_SHA1=$(sha1 $DATA_DIR/new.file)
78NEW_SIZE=$(stat -c %s $DATA_DIR/new.file)
79
80# --------------- basic execution ----------------------
81
82testname "usage message"
83run_command $WORK_DIR/applypatch && fail
84
85testname "display license"
86run_command $WORK_DIR/applypatch -l | grep -q -i copyright || fail
87
88
89# --------------- check mode ----------------------
90
91$ADB push $DATA_DIR/old.file $WORK_DIR
92
93testname "check mode single"
94run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
95
96testname "check mode multiple"
97run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
98
99testname "check mode failure"
100run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
101
102$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
103# put some junk in the old file
104run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
105
106testname "check mode cache (corrupted) single"
107run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
108
109testname "check mode cache (corrupted) multiple"
110run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
111
112testname "check mode cache (corrupted) failure"
113run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
114
115# remove the old file entirely
116run_command rm $WORK_DIR/old.file
117
118testname "check mode cache (missing) single"
119run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
120
121testname "check mode cache (missing) multiple"
122run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
123
124testname "check mode cache (missing) failure"
125run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
126
127
128# --------------- apply patch ----------------------
129
130$ADB push $DATA_DIR/old.file $WORK_DIR
131$ADB push $DATA_DIR/patch.xdelta3 $WORK_DIR
132
133# Check that the partition has enough space to apply the patch without
134# copying. If it doesn't, we'll be testing the low-space condition
135# when we intend to test the not-low-space condition.
136testname "apply patches (with enough space)"
137free_kb=$(free_space $WORK_FS)
138echo "${free_kb}kb free on /$WORK_FS."
139if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then
140 echo "Not enough space on /$WORK_FS to patch test file."
141 echo
142 echo "This doesn't mean that applypatch is necessarily broken;"
143 echo "just that /$WORK_FS doesn't have enough free space to"
144 echo "properly run this test."
145 exit 1
146fi
147
148testname "apply xdelta3 patch"
149run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.xdelta3 || fail
150$ADB pull $WORK_DIR/old.file $tmpdir/patched
151diff -q $DATA_DIR/new.file $tmpdir/patched || fail
152
153testname "reapply xdelta3 patch"
154run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.xdelta3 || fail
155$ADB pull $WORK_DIR/old.file $tmpdir/patched
156diff -q $DATA_DIR/new.file $tmpdir/patched || fail
157
158$ADB push $DATA_DIR/old.file $WORK_DIR
159$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
160
161testname "apply bsdiff patch"
162run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
163$ADB pull $WORK_DIR/old.file $tmpdir/patched
164diff -q $DATA_DIR/new.file $tmpdir/patched || fail
165
166testname "reapply bsdiff patch"
167run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
168$ADB pull $WORK_DIR/old.file $tmpdir/patched
169diff -q $DATA_DIR/new.file $tmpdir/patched || fail
170
171
172# --------------- apply patch with low space on /system ----------------------
173
174$ADB push $DATA_DIR/old.file $WORK_DIR
175$ADB push $DATA_DIR/patch.xdelta3 $WORK_DIR
176$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
177
178free_kb=$(free_space $WORK_FS)
179echo "${free_kb}kb free on /$WORK_FS; we'll soon fix that."
180echo run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
181run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
182free_kb=$(free_space $WORK_FS)
183echo "${free_kb}kb free on /$WORK_FS now."
184
185testname "apply xdelta3 patch with low space"
186run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.xdelta3 || fail
187$ADB pull $WORK_DIR/old.file $tmpdir/patched
188diff -q $DATA_DIR/new.file $tmpdir/patched || fail
189
190testname "reapply xdelta3 patch with low space"
191run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.xdelta3 || fail
192$ADB pull $WORK_DIR/old.file $tmpdir/patched
193diff -q $DATA_DIR/new.file $tmpdir/patched || fail
194
195$ADB push $DATA_DIR/old.file $WORK_DIR
196
197testname "apply bsdiff patch with low space"
198run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
199$ADB pull $WORK_DIR/old.file $tmpdir/patched
200diff -q $DATA_DIR/new.file $tmpdir/patched || fail
201
202testname "reapply bsdiff patch with low space"
203run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
204$ADB pull $WORK_DIR/old.file $tmpdir/patched
205diff -q $DATA_DIR/new.file $tmpdir/patched || fail
206
207# --------------- apply patch with low space on /system and /cache ----------------------
208
209$ADB push $DATA_DIR/old.file $WORK_DIR
210$ADB push $DATA_DIR/patch.xdelta3 $WORK_DIR
211$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
212
213free_kb=$(free_space $WORK_FS)
214echo "${free_kb}kb free on /$WORK_FS"
215
216run_command mkdir /cache/subdir
217run_command 'echo > /cache/subdir/a.file'
218run_command 'echo > /cache/a.file'
219run_command mkdir -p /cache/recovery/otatest
220run_command 'echo > /cache/recovery/otatest/b.file'
221run_command "echo > $CACHE_TEMP_SOURCE"
222free_kb=$(free_space cache)
223echo "${free_kb}kb free on /cache; we'll soon fix that."
224run_command dd if=/dev/zero of=/cache/bloat_small.dat count=128 bs=1024 || fail
225run_command dd if=/dev/zero of=/cache/bloat_large.dat count=$((free_kb-640)) bs=1024 || fail
226free_kb=$(free_space cache)
227echo "${free_kb}kb free on /cache now."
228
229testname "apply bsdiff patch with low space, full cache, can't delete enough"
230$ADB shell 'cat >> /cache/bloat_large.dat' & open_pid=$!
231echo "open_pid is $open_pid"
232
233# size check should fail even though it deletes some stuff
234run_command $WORK_DIR/applypatch -s $NEW_SIZE && fail
235run_command ls /cache/bloat_small.dat && fail # was deleted
236run_command ls /cache/a.file && fail # was deleted
237run_command ls /cache/recovery/otatest/b.file && fail # was deleted
238run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open
239run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir
240run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
241
242# should fail; not enough files can be deleted
243run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff && fail
244run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open
245run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir
246run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
247
248kill $open_pid # /cache/bloat_large.dat is no longer open
249
250testname "apply bsdiff patch with low space, full cache, can delete enough"
251
252# should succeed after deleting /cache/bloat_large.dat
253run_command $WORK_DIR/applypatch -s $NEW_SIZE || fail
254run_command ls /cache/bloat_large.dat && fail # was deleted
255run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir
256run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
257
258# should succeed
259run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
260$ADB pull $WORK_DIR/old.file $tmpdir/patched
261diff -q $DATA_DIR/new.file $tmpdir/patched || fail
262run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir
263run_command ls $CACHE_TEMP_SOURCE && fail # was deleted because patching overwrote it, then deleted it
264
265# --------------- apply patch from cache ----------------------
266
267$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
268# put some junk in the old file
269run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
270
271testname "apply xdelta3 patch from cache (corrupted source) with low space"
272run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.xdelta3 || fail
273$ADB pull $WORK_DIR/old.file $tmpdir/patched
274diff -q $DATA_DIR/new.file $tmpdir/patched || fail
275
276$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
277# remove the old file entirely
278run_command rm $WORK_DIR/old.file
279
280testname "apply bsdiff patch from cache (missing source) with low space"
281run_command $WORK_DIR/applypatch $WORK_DIR/old.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
282$ADB pull $WORK_DIR/old.file $tmpdir/patched
283diff -q $DATA_DIR/new.file $tmpdir/patched || fail
284
285
286# --------------- cleanup ----------------------
287
288# not necessary if we're about to kill the emulator, but nice for
289# running on real devices or already-running emulators.
290run_command rm /cache/bloat*.dat $WORK_DIR/bloat.dat $CACHE_TEMP_SOURCE $WORK_DIR/old.file $WORK_DIR/patch.xdelta3 $WORK_DIR/patch.bsdiff $WORK_DIR/applypatch
291
292kill $pid_emulator
293
294rm -rf $tmpdir
295
296echo
297echo PASS
298echo
299