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
22294651d7b4e56559822894ccc520f194363d10d8Tao Baofrom blockimgdiff import (BlockImageDiff, EmptyImage, HeapItem, ImgdiffStats,
23294651d7b4e56559822894ccc520f194363d10d8Tao Bao                          Transfer)
24334822842353669df47cec08500d4497b4b353eaTao Baofrom rangelib import RangeSet
25334822842353669df47cec08500d4497b4b353eaTao Bao
26186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
27186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Baoclass HealpItemTest(unittest.TestCase):
28186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
29186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  class Item(object):
30186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    def __init__(self, score):
31186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao      self.score = score
32186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
33186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  def test_init(self):
34186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item1 = HeapItem(self.Item(15))
35186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item2 = HeapItem(self.Item(20))
36186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item3 = HeapItem(self.Item(15))
37186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item1)
38186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item2)
39186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item3)
40186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
41186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertNotEqual(item1, item2)
42186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertEqual(item1, item3)
43186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    # HeapItem uses negated scores.
44186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertGreater(item1, item2)
45186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertLessEqual(item1, item3)
46186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item1 <= item3)
47186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertFalse(item2 >= item1)
48186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
49186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao  def test_clear(self):
50186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item = HeapItem(self.Item(15))
51186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertTrue(item)
52186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
53186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    item.clear()
54186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao    self.assertFalse(item)
55186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
56186ec99eb9a5580bbd6404ba61b5210f524d65aaTao Bao
57334822842353669df47cec08500d4497b4b353eaTao Baoclass BlockImageDiffTest(unittest.TestCase):
58334822842353669df47cec08500d4497b4b353eaTao Bao
59334822842353669df47cec08500d4497b4b353eaTao Bao  def test_GenerateDigraphOrder(self):
60334822842353669df47cec08500d4497b4b353eaTao Bao    """Make sure GenerateDigraph preserves the order.
61334822842353669df47cec08500d4497b4b353eaTao Bao
62334822842353669df47cec08500d4497b4b353eaTao Bao    t0: <0-5> => <...>
63334822842353669df47cec08500d4497b4b353eaTao Bao    t1: <0-7> => <...>
64334822842353669df47cec08500d4497b4b353eaTao Bao    t2: <0-4> => <...>
65334822842353669df47cec08500d4497b4b353eaTao Bao    t3: <...> => <0-10>
66334822842353669df47cec08500d4497b4b353eaTao Bao
67334822842353669df47cec08500d4497b4b353eaTao Bao    t0, t1 and t2 must go before t3, i.e. t3.goes_after =
68334822842353669df47cec08500d4497b4b353eaTao Bao    { t0:..., t1:..., t2:... }. But the order of t0-t2 must be preserved.
69334822842353669df47cec08500d4497b4b353eaTao Bao    """
70334822842353669df47cec08500d4497b4b353eaTao Bao
71334822842353669df47cec08500d4497b4b353eaTao Bao    src = EmptyImage()
72334822842353669df47cec08500d4497b4b353eaTao Bao    tgt = EmptyImage()
73334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff = BlockImageDiff(tgt, src)
74334822842353669df47cec08500d4497b4b353eaTao Bao
75334822842353669df47cec08500d4497b4b353eaTao Bao    transfers = block_image_diff.transfers
76a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t0 = Transfer("t1", "t1", RangeSet("10-15"), RangeSet("0-5"), "t1hash",
77a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t1hash", "move", transfers)
78a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t1 = Transfer("t2", "t2", RangeSet("20-25"), RangeSet("0-7"), "t2hash",
79a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t2hash", "move", transfers)
80a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t2 = Transfer("t3", "t3", RangeSet("30-35"), RangeSet("0-4"), "t3hash",
81a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t3hash", "move", transfers)
82a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t3 = Transfer("t4", "t4", RangeSet("0-10"), RangeSet("40-50"), "t4hash",
83a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t4hash", "move", transfers)
84334822842353669df47cec08500d4497b4b353eaTao Bao
85334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff.GenerateDigraph()
86334822842353669df47cec08500d4497b4b353eaTao Bao    t3_goes_after_copy = t3.goes_after.copy()
87334822842353669df47cec08500d4497b4b353eaTao Bao
88334822842353669df47cec08500d4497b4b353eaTao Bao    # Elements in the set must be in the transfer evaluation order.
89334822842353669df47cec08500d4497b4b353eaTao Bao    elements = list(t3_goes_after_copy)
90334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t0, elements[0])
91334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t1, elements[1])
92334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t2, elements[2])
93334822842353669df47cec08500d4497b4b353eaTao Bao
94334822842353669df47cec08500d4497b4b353eaTao Bao    # Now switch the order of t0, t1 and t2.
95334822842353669df47cec08500d4497b4b353eaTao Bao    transfers[0], transfers[1], transfers[2] = (
96334822842353669df47cec08500d4497b4b353eaTao Bao        transfers[2], transfers[0], transfers[1])
97334822842353669df47cec08500d4497b4b353eaTao Bao    t3.goes_after.clear()
98334822842353669df47cec08500d4497b4b353eaTao Bao    t3.goes_before.clear()
99334822842353669df47cec08500d4497b4b353eaTao Bao    block_image_diff.GenerateDigraph()
100334822842353669df47cec08500d4497b4b353eaTao Bao
101334822842353669df47cec08500d4497b4b353eaTao Bao    # The goes_after must be different from last run.
102334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertNotEqual(t3_goes_after_copy, t3.goes_after)
103334822842353669df47cec08500d4497b4b353eaTao Bao
104334822842353669df47cec08500d4497b4b353eaTao Bao    # Assert that each element must agree with the transfer order.
105334822842353669df47cec08500d4497b4b353eaTao Bao    elements = list(t3.goes_after)
106334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t2, elements[0])
107334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t0, elements[1])
108334822842353669df47cec08500d4497b4b353eaTao Bao    self.assertEqual(t1, elements[2])
109304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
110304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao  def test_ReviseStashSize(self):
111304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """ReviseStashSize should convert transfers to 'new' commands as needed.
112304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
113304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1: diff <20-29> => <11-15>
114304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2: diff <11-15> => <20-29>
115304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """
116304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
117304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    src = EmptyImage()
118304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    tgt = EmptyImage()
119304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff = BlockImageDiff(tgt, src, version=3)
120304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
121304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    transfers = block_image_diff.transfers
122a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    Transfer("t1", "t1", RangeSet("11-15"), RangeSet("20-29"), "t1hash",
123a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu             "t1hash", "diff", transfers)
124a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    Transfer("t2", "t2", RangeSet("20-29"), RangeSet("11-15"), "t2hash",
125a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu             "t2hash", "diff", transfers)
126304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
127304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.GenerateDigraph()
128304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.FindVertexSequence()
129304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.ReverseBackwardEdges()
130304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
131304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Sufficient cache to stash 5 blocks (size * 0.8 >= 5).
132304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 7 * 4096
133304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(0, block_image_diff.ReviseStashSize())
134304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
135304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Insufficient cache to stash 5 blocks (size * 0.8 < 5).
136304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 6 * 4096
137304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(10, block_image_diff.ReviseStashSize())
138304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
139304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao  def test_ReviseStashSize_bug_33687949(self):
140304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """ReviseStashSize() should "free" the used stash _after_ the command.
141304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
142304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1: diff <1-5> => <11-15>
143304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2: diff <11-15> => <21-25>
144304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3: diff <11-15 30-39> => <1-5 30-39>
145304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
146304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    For transfer t3, the used stash "11-15" should not be freed until the
147304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    command finishes. Assume the allowed cache size is 12-block, it should
148304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    convert the command to 'new' due to insufficient cache (12 < 5 + 10).
149304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    """
150304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
151304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    src = EmptyImage()
152304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    tgt = EmptyImage()
153304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff = BlockImageDiff(tgt, src, version=3)
154304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
155304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    transfers = block_image_diff.transfers
156a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t1 = Transfer("t1", "t1", RangeSet("11-15"), RangeSet("1-5"), "t1hash",
157a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t1hash", "diff", transfers)
158a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu    t2 = Transfer("t2", "t2", RangeSet("21-25"), RangeSet("11-15"), "t2hash",
159a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t2hash", "diff", transfers)
160304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3 = Transfer("t3", "t3", RangeSet("1-5 30-39"), RangeSet("11-15 30-39"),
161a011dec9b28c03e3f8283de0a0e503f57f73973aTianjie Xu                  "t3hash", "t3hash", "diff", transfers)
162304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
163304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    block_image_diff.GenerateDigraph()
164304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
165304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Instead of calling FindVertexSequence() and ReverseBackwardEdges(), we
166304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # just set up the stash_before and use_stash manually. Otherwise it will
167304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # reorder the transfer, which makes testing ReviseStashSize() harder.
168304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1.stash_before.append((0, RangeSet("11-15")))
169304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t2.use_stash.append((0, RangeSet("11-15")))
170304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t1.stash_before.append((1, RangeSet("11-15")))
171304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    t3.use_stash.append((1, RangeSet("11-15")))
172304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao
173304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    # Insufficient cache to stash 15 blocks (size * 0.8 < 15).
174304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    common.OPTIONS.cache_size = 15 * 4096
175304ee27e889d0b16c66a9b5d2faed379f8cad627Tao Bao    self.assertEqual(15, block_image_diff.ReviseStashSize())
176cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
177cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_FileTypeSupportedByImgdiff(self):
178cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
179cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
180cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/priv-app/Settings/Settings.apk"))
181cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
182cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
183cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/framework/am.jar"))
184cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
185cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
186cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/etc/security/otacerts.zip"))
187cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
188cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
189cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
190cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/framework/arm/boot.oat"))
191cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
192cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        BlockImageDiff.FileTypeSupportedByImgdiff(
193cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/priv-app/notanapk"))
194cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
195cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_CanUseImgdiff(self):
196cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
197cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertTrue(
198cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
199cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
200294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertTrue(
201294651d7b4e56559822894ccc520f194363d10d8Tao Bao        block_image_diff.CanUseImgdiff(
202294651d7b4e56559822894ccc520f194363d10d8Tao Bao            "/vendor/app/app2.apk", RangeSet("20 25"), RangeSet("30-31"), True))
203294651d7b4e56559822894ccc520f194363d10d8Tao Bao
204294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertDictEqual(
205294651d7b4e56559822894ccc520f194363d10d8Tao Bao        {
206294651d7b4e56559822894ccc520f194363d10d8Tao Bao            ImgdiffStats.USED_IMGDIFF : {"/system/app/app1.apk"},
207294651d7b4e56559822894ccc520f194363d10d8Tao Bao            ImgdiffStats.USED_IMGDIFF_LARGE_APK : {"/vendor/app/app2.apk"},
208294651d7b4e56559822894ccc520f194363d10d8Tao Bao        },
209294651d7b4e56559822894ccc520f194363d10d8Tao Bao        block_image_diff.imgdiff_stats.stats)
210294651d7b4e56559822894ccc520f194363d10d8Tao Bao
211cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
212cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao  def test_CanUseImgdiff_ineligible(self):
213cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # Disabled by caller.
214cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage(),
215cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao                                      disable_imgdiff=True)
216cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
217cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
218cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
219cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
220cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # Unsupported file type.
221cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
222cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
223cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
224cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/bin/gzip", RangeSet("10-15"), RangeSet("0-5")))
225cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
226cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # At least one of the ranges is in non-monotonic order.
227cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
228cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
229cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/system/app/app2.apk", RangeSet("10-15"),
230cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            RangeSet("15-20 30 10-14")))
231cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao
232cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    # At least one of the ranges has been modified.
233cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    src_ranges = RangeSet("0-5")
234cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    src_ranges.extra['trimmed'] = True
235cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao    self.assertFalse(
236cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao        block_image_diff.CanUseImgdiff(
237cb73aed1f00ebafe2b9319ec20e41734da9d6b88Tao Bao            "/vendor/app/app3.apk", RangeSet("10-15"), src_ranges))
238294651d7b4e56559822894ccc520f194363d10d8Tao Bao
2394ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao    # At least one of the ranges is incomplete.
2404ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao    src_ranges = RangeSet("0-5")
2414ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao    src_ranges.extra['incomplete'] = True
2424ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao    self.assertFalse(
2434ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao        block_image_diff.CanUseImgdiff(
2444ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao            "/vendor/app/app4.apk", RangeSet("10-15"), src_ranges))
2454ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao
246294651d7b4e56559822894ccc520f194363d10d8Tao Bao    # The stats are correctly logged.
247294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertDictEqual(
248294651d7b4e56559822894ccc520f194363d10d8Tao Bao        {
249294651d7b4e56559822894ccc520f194363d10d8Tao Bao            ImgdiffStats.SKIPPED_NONMONOTONIC : {'/system/app/app2.apk'},
250294651d7b4e56559822894ccc520f194363d10d8Tao Bao            ImgdiffStats.SKIPPED_TRIMMED : {'/vendor/app/app3.apk'},
2514ccea8549e889b4d4a17ccc11f3fb71dd97369efTao Bao            ImgdiffStats.SKIPPED_INCOMPLETE: {'/vendor/app/app4.apk'},
252294651d7b4e56559822894ccc520f194363d10d8Tao Bao        },
253294651d7b4e56559822894ccc520f194363d10d8Tao Bao        block_image_diff.imgdiff_stats.stats)
254294651d7b4e56559822894ccc520f194363d10d8Tao Bao
255294651d7b4e56559822894ccc520f194363d10d8Tao Bao
256294651d7b4e56559822894ccc520f194363d10d8Tao Baoclass ImgdiffStatsTest(unittest.TestCase):
257294651d7b4e56559822894ccc520f194363d10d8Tao Bao
258294651d7b4e56559822894ccc520f194363d10d8Tao Bao  def test_Log(self):
259294651d7b4e56559822894ccc520f194363d10d8Tao Bao    imgdiff_stats = ImgdiffStats()
260294651d7b4e56559822894ccc520f194363d10d8Tao Bao    imgdiff_stats.Log("/system/app/app2.apk", ImgdiffStats.USED_IMGDIFF)
261294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertDictEqual(
262294651d7b4e56559822894ccc520f194363d10d8Tao Bao        {
263294651d7b4e56559822894ccc520f194363d10d8Tao Bao            ImgdiffStats.USED_IMGDIFF: {'/system/app/app2.apk'},
264294651d7b4e56559822894ccc520f194363d10d8Tao Bao        },
265294651d7b4e56559822894ccc520f194363d10d8Tao Bao        imgdiff_stats.stats)
266294651d7b4e56559822894ccc520f194363d10d8Tao Bao
267294651d7b4e56559822894ccc520f194363d10d8Tao Bao  def test_Log_invalidInputs(self):
268294651d7b4e56559822894ccc520f194363d10d8Tao Bao    imgdiff_stats = ImgdiffStats()
269294651d7b4e56559822894ccc520f194363d10d8Tao Bao
270294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertRaises(AssertionError, imgdiff_stats.Log, "/system/bin/gzip",
271294651d7b4e56559822894ccc520f194363d10d8Tao Bao                      ImgdiffStats.USED_IMGDIFF)
272294651d7b4e56559822894ccc520f194363d10d8Tao Bao
273294651d7b4e56559822894ccc520f194363d10d8Tao Bao    self.assertRaises(AssertionError, imgdiff_stats.Log, "/system/app/app1.apk",
274294651d7b4e56559822894ccc520f194363d10d8Tao Bao                      "invalid reason")
275