test_blockimgdiff.py revision cb73aed1f00ebafe2b9319ec20e41734da9d6b88
1334822842353669df47cec08500d4497b4b353eaTao Bao#
2334822842353669df47cec08500d4497b4b353eaTao Bao# Copyright (C) 2016 The Android Open Source Project
3334822842353669df47cec08500d4497b4b353eaTao Bao#
4334822842353669df47cec08500d4497b4b353eaTao Bao# Licensed under the Apache License, Version 2.0 (the "License");
5334822842353669df47cec08500d4497b4b353eaTao Bao# you may not use this file except in compliance with the License.
6334822842353669df47cec08500d4497b4b353eaTao Bao# You may obtain a copy of the License at
7334822842353669df47cec08500d4497b4b353eaTao Bao#
8334822842353669df47cec08500d4497b4b353eaTao Bao#      http://www.apache.org/licenses/LICENSE-2.0
9334822842353669df47cec08500d4497b4b353eaTao Bao#
10334822842353669df47cec08500d4497b4b353eaTao Bao# Unless required by applicable law or agreed to in writing, software
11334822842353669df47cec08500d4497b4b353eaTao Bao# distributed under the License is distributed on an "AS IS" BASIS,
12334822842353669df47cec08500d4497b4b353eaTao Bao# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13334822842353669df47cec08500d4497b4b353eaTao Bao# See the License for the specific language governing permissions and
14334822842353669df47cec08500d4497b4b353eaTao Bao# limitations under the License.
15334822842353669df47cec08500d4497b4b353eaTao Bao#
16334822842353669df47cec08500d4497b4b353eaTao Bao
17334822842353669df47cec08500d4497b4b353eaTao Baofrom __future__ import print_function
18334822842353669df47cec08500d4497b4b353eaTao Bao
19334822842353669df47cec08500d4497b4b353eaTao Baoimport unittest
20334822842353669df47cec08500d4497b4b353eaTao Bao
21186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Baoimport common
22186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Baofrom blockimgdiff import BlockImageDiff, EmptyImage, HeapItem, Transfer
23334822842353669df47cec08500d4497b4b353eaTao Baofrom rangelib import RangeSet
24334822842353669df47cec08500d4497b4b353eaTao Bao
25186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
26186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Baoclass HealpItemTest(unittest.TestCase):
27186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
28186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  class Item(object):
29186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    def __init__(self, score):
30186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao      self.score = score
31186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
32186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  def test_init(self):
33186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item1 = HeapItem(self.Item(15))
34186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item2 = HeapItem(self.Item(20))
35186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item3 = HeapItem(self.Item(15))
36186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item1)
37186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item2)
38186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item3)
39186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
40186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertNotEqual(item1, item2)
41186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertEqual(item1, item3)
42186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    # HeapItem uses negated scores.
43186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertGreater(item1, item2)
44186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertLessEqual(item1, item3)
45186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item1 <= item3)
46186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertFalse(item2 >= item1)
47186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
48186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  def test_clear(self):
49186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item = HeapItem(self.Item(15))
50186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item)
51186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
52186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item.clear()
53186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertFalse(item)
54186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
55186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
56334822842353669df47cec08500d4497b4b353eaTao Baoclass BlockImageDiffTest(unittest.TestCase):
57334822842353669df47cec08500d4497b4b353eaTao Bao
58334822842353669df47cec08500d4497b4b353eaTao Bao  def test_GenerateDigraphOrder(self):
59334822842353669df47cec08500d4497b4b353eaTao Bao    """Make sure GenerateDigraph preserves the order.
60334822842353669df47cec08500d4497b4b353eaTao Bao
61334822842353669df47cec08500d4497b4b353eaTao Bao    t0: <0-5> => <...>
62334822842353669df47cec08500d4497b4b353eaTao Bao    t1: <0-7> => <...>
63334822842353669df47cec08500d4497b4b353eaTao Bao    t2: <0-4> => <...>
64334822842353669df47cec08500d4497b4b353eaTao Bao    t3: <...> => <0-10>
65334822842353669df47cec08500d4497b4b353eaTao Bao
66334822842353669df47cec08500d4497b4b353eaTao Bao    t0, t1 and t2 must go before t3, i.e. t3.goes_after =
67334822842353669df47cec08500d4497b4b353eaTao Bao    { t0:..., t1:..., t2:... }. But the order of t0-t2 must be preserved.
68334822842353669df47cec08500d4497b4b353eaTao Bao    """
69334822842353669df47cec08500d4497b4b353eaTao Bao
70334822842353669df47cec08500d4497b4b353eaTao Bao    src = EmptyImage()
71334822842353669df47cec08500d4497b4b353eaTao Bao    tgt = EmptyImage()
72334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff = BlockImageDiff(tgt, src)
73334822842353669df47cec08500d4497b4b353eaTao Bao
74334822842353669df47cec08500d4497b4b353eaTao Bao    transfers = block_image_diff.transfers
75a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t0 = Transfer("t1", "t1", RangeSet("10-15"), RangeSet("0-5"), "t1hash",
76a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t1hash", "move", transfers)
77a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t1 = Transfer("t2", "t2", RangeSet("20-25"), RangeSet("0-7"), "t2hash",
78a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t2hash", "move", transfers)
79a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t2 = Transfer("t3", "t3", RangeSet("30-35"), RangeSet("0-4"), "t3hash",
80a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t3hash", "move", transfers)
81a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t3 = Transfer("t4", "t4", RangeSet("0-10"), RangeSet("40-50"), "t4hash",
82a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t4hash", "move", transfers)
83334822842353669df47cec08500d4497b4b353eaTao Bao
84334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff.GenerateDigraph()
85334822842353669df47cec08500d4497b4b353eaTao Bao    t3_goes_after_copy = t3.goes_after.copy()
86334822842353669df47cec08500d4497b4b353eaTao Bao
87334822842353669df47cec08500d4497b4b353eaTao Bao    # Elements in the set must be in the transfer evaluation order.
88334822842353669df47cec08500d4497b4b353eaTao Bao    elements = list(t3_goes_after_copy)
89334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t0, elements[0])
90334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t1, elements[1])
91334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t2, elements[2])
92334822842353669df47cec08500d4497b4b353eaTao Bao
93334822842353669df47cec08500d4497b4b353eaTao Bao    # Now switch the order of t0, t1 and t2.
94334822842353669df47cec08500d4497b4b353eaTao Bao    transfers[0], transfers[1], transfers[2] = (
95334822842353669df47cec08500d4497b4b353eaTao Bao        transfers[2], transfers[0], transfers[1])
96334822842353669df47cec08500d4497b4b353eaTao Bao    t3.goes_after.clear()
97334822842353669df47cec08500d4497b4b353eaTao Bao    t3.goes_before.clear()
98334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff.GenerateDigraph()
99334822842353669df47cec08500d4497b4b353eaTao Bao
100334822842353669df47cec08500d4497b4b353eaTao Bao    # The goes_after must be different from last run.
101334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertNotEqual(t3_goes_after_copy, t3.goes_after)
102334822842353669df47cec08500d4497b4b353eaTao Bao
103334822842353669df47cec08500d4497b4b353eaTao Bao    # Assert that each element must agree with the transfer order.
104334822842353669df47cec08500d4497b4b353eaTao Bao    elements = list(t3.goes_after)
105334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t2, elements[0])
106334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t0, elements[1])
107334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t1, elements[2])
108304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
109304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao  def test_ReviseStashSize(self):
110304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """ReviseStashSize should convert transfers to 'new' commands as needed.
111304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
112304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1: diff <20-29> => <11-15>
113304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2: diff <11-15> => <20-29>
114304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """
115304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
116304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    src = EmptyImage()
117304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    tgt = EmptyImage()
118304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff = BlockImageDiff(tgt, src, version=3)
119304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
120304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    transfers = block_image_diff.transfers
121a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    Transfer("t1", "t1", RangeSet("11-15"), RangeSet("20-29"), "t1hash",
122a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu             "t1hash", "diff", transfers)
123a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    Transfer("t2", "t2", RangeSet("20-29"), RangeSet("11-15"), "t2hash",
124a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu             "t2hash", "diff", transfers)
125304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
126304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.GenerateDigraph()
127304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.FindVertexSequence()
128304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.ReverseBackwardEdges()
129304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
130304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Sufficient cache to stash 5 blocks (size * 0.8 >= 5).
131304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 7 * 4096
132304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(0, block_image_diff.ReviseStashSize())
133304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
134304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Insufficient cache to stash 5 blocks (size * 0.8 < 5).
135304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 6 * 4096
136304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(10, block_image_diff.ReviseStashSize())
137304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
138304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao  def test_ReviseStashSize_bug_33687949(self):
139304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """ReviseStashSize() should "free" the used stash _after_ the command.
140304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
141304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1: diff <1-5> => <11-15>
142304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2: diff <11-15> => <21-25>
143304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3: diff <11-15 30-39> => <1-5 30-39>
144304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
145304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    For transfer t3, the used stash "11-15" should not be freed until the
146304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    command finishes. Assume the allowed cache size is 12-block, it should
147304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    convert the command to 'new' due to insufficient cache (12 < 5 + 10).
148304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """
149304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
150304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    src = EmptyImage()
151304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    tgt = EmptyImage()
152304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff = BlockImageDiff(tgt, src, version=3)
153304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
154304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    transfers = block_image_diff.transfers
155a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t1 = Transfer("t1", "t1", RangeSet("11-15"), RangeSet("1-5"), "t1hash",
156a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t1hash", "diff", transfers)
157a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t2 = Transfer("t2", "t2", RangeSet("21-25"), RangeSet("11-15"), "t2hash",
158a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t2hash", "diff", transfers)
159304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3 = Transfer("t3", "t3", RangeSet("1-5 30-39"), RangeSet("11-15 30-39"),
160a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t3hash", "t3hash", "diff", transfers)
161304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
162304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.GenerateDigraph()
163304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
164304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Instead of calling FindVertexSequence() and ReverseBackwardEdges(), we
165304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # just set up the stash_before and use_stash manually. Otherwise it will
166304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # reorder the transfer, which makes testing ReviseStashSize() harder.
167304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1.stash_before.append((0, RangeSet("11-15")))
168304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2.use_stash.append((0, RangeSet("11-15")))
169304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1.stash_before.append((1, RangeSet("11-15")))
170304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3.use_stash.append((1, RangeSet("11-15")))
171304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
172304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Insufficient cache to stash 15 blocks (size * 0.8 < 15).
173304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 15 * 4096
174304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(15, block_image_diff.ReviseStashSize())
175cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
176cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_FileTypeSupportedByImgdiff(self):
177cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
178cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
179cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/priv-app/Settings/Settings.apk"))
180cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
181cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
182cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/framework/am.jar"))
183cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
184cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
185cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/etc/security/otacerts.zip"))
186cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
187cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
188cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
189cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/framework/arm/boot.oat"))
190cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
191cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
192cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/priv-app/notanapk"))
193cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
194cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_CanUseImgdiff(self):
195cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
196cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
197cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
198cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
199cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
200cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_CanUseImgdiff_ineligible(self):
201cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # Disabled by caller.
202cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage(),
203cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao                                      disable_imgdiff=True)
204cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
205cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
206cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
207cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
208cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # Unsupported file type.
209cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
210cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
211cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
212cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/bin/gzip", RangeSet("10-15"), RangeSet("0-5")))
213cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
214cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # At least one of the ranges is in non-monotonic order.
215cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
216cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
217cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app2.apk", RangeSet("10-15"),
218cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            RangeSet("15-20 30 10-14")))
219cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
220cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # At least one of the ranges has been modified.
221cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    src_ranges = RangeSet("0-5")
222cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    src_ranges.extra['trimmed'] = True
223cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
224cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
225cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/vendor/app/app3.apk", RangeSet("10-15"), src_ranges))
226