blob: a22373f624ed40944c4b4ea5b47047922e849151 [file] [log] [blame]
Gilad Arnoldf583a7d2015-02-05 13:23:55 -08001#!/usr/bin/python2
Gilad Arnold5502b562013-03-08 13:22:31 -08002#
3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Unit testing checker.py."""
8
Gilad Arnoldf583a7d2015-02-05 13:23:55 -08009from __future__ import print_function
10
Gilad Arnold5502b562013-03-08 13:22:31 -080011import array
12import collections
13import cStringIO
14import hashlib
15import itertools
16import os
17import unittest
18
Gilad Arnoldcb638912013-06-24 04:57:11 -070019# pylint cannot find mox.
Gilad Arnold5502b562013-03-08 13:22:31 -080020# pylint: disable=F0401
21import mox
22
23import checker
24import common
Gilad Arnoldcb638912013-06-24 04:57:11 -070025import payload as update_payload # Avoid name conflicts later.
Gilad Arnold5502b562013-03-08 13:22:31 -080026import test_utils
27import update_metadata_pb2
28
29
Gilad Arnold5502b562013-03-08 13:22:31 -080030def _OpTypeByName(op_name):
31 op_name_to_type = {
32 'REPLACE': common.OpType.REPLACE,
33 'REPLACE_BZ': common.OpType.REPLACE_BZ,
34 'MOVE': common.OpType.MOVE,
35 'BSDIFF': common.OpType.BSDIFF,
Allie Woodf5c4f3e2015-02-20 16:57:46 -080036 'SOURCE_COPY': common.OpType.SOURCE_COPY,
37 'SOURCE_BSDIFF': common.OpType.SOURCE_BSDIFF,
Gilad Arnold5502b562013-03-08 13:22:31 -080038 }
39 return op_name_to_type[op_name]
40
41
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070042def _GetPayloadChecker(payload_gen_write_to_file_func, payload_gen_dargs=None,
43 checker_init_dargs=None):
Gilad Arnold5502b562013-03-08 13:22:31 -080044 """Returns a payload checker from a given payload generator."""
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070045 if payload_gen_dargs is None:
46 payload_gen_dargs = {}
47 if checker_init_dargs is None:
48 checker_init_dargs = {}
49
Gilad Arnold5502b562013-03-08 13:22:31 -080050 payload_file = cStringIO.StringIO()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070051 payload_gen_write_to_file_func(payload_file, **payload_gen_dargs)
Gilad Arnold5502b562013-03-08 13:22:31 -080052 payload_file.seek(0)
53 payload = update_payload.Payload(payload_file)
54 payload.Init()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070055 return checker.PayloadChecker(payload, **checker_init_dargs)
Gilad Arnold5502b562013-03-08 13:22:31 -080056
57
58def _GetPayloadCheckerWithData(payload_gen):
59 """Returns a payload checker from a given payload generator."""
60 payload_file = cStringIO.StringIO()
61 payload_gen.WriteToFile(payload_file)
62 payload_file.seek(0)
63 payload = update_payload.Payload(payload_file)
64 payload.Init()
65 return checker.PayloadChecker(payload)
66
67
Gilad Arnoldcb638912013-06-24 04:57:11 -070068# This class doesn't need an __init__().
Gilad Arnold5502b562013-03-08 13:22:31 -080069# pylint: disable=W0232
Gilad Arnoldcb638912013-06-24 04:57:11 -070070# Unit testing is all about running protected methods.
Gilad Arnold5502b562013-03-08 13:22:31 -080071# pylint: disable=W0212
Gilad Arnoldcb638912013-06-24 04:57:11 -070072# Don't bark about missing members of classes you cannot import.
Gilad Arnold5502b562013-03-08 13:22:31 -080073# pylint: disable=E1101
74class PayloadCheckerTest(mox.MoxTestBase):
75 """Tests the PayloadChecker class.
76
77 In addition to ordinary testFoo() methods, which are automatically invoked by
78 the unittest framework, in this class we make use of DoBarTest() calls that
79 implement parametric tests of certain features. In order to invoke each test,
80 which embodies a unique combination of parameter values, as a complete unit
81 test, we perform explicit enumeration of the parameter space and create
82 individual invocation contexts for each, which are then bound as
83 testBar__param1=val1__param2=val2(). The enumeration of parameter spaces for
84 all such tests is done in AddAllParametricTests().
Gilad Arnold5502b562013-03-08 13:22:31 -080085 """
86
87 def MockPayload(self):
Allie Woodf5c4f3e2015-02-20 16:57:46 -080088 """Create a mock payload object, complete with a mock manifest."""
Gilad Arnold5502b562013-03-08 13:22:31 -080089 payload = self.mox.CreateMock(update_payload.Payload)
90 payload.is_init = True
91 payload.manifest = self.mox.CreateMock(
92 update_metadata_pb2.DeltaArchiveManifest)
93 return payload
94
95 @staticmethod
96 def NewExtent(start_block, num_blocks):
97 """Returns an Extent message.
98
99 Each of the provided fields is set iff it is >= 0; otherwise, it's left at
100 its default state.
101
102 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700103 start_block: The starting block of the extent.
104 num_blocks: The number of blocks in the extent.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800105
Gilad Arnold5502b562013-03-08 13:22:31 -0800106 Returns:
107 An Extent message.
Gilad Arnold5502b562013-03-08 13:22:31 -0800108 """
109 ex = update_metadata_pb2.Extent()
110 if start_block >= 0:
111 ex.start_block = start_block
112 if num_blocks >= 0:
113 ex.num_blocks = num_blocks
114 return ex
115
116 @staticmethod
117 def NewExtentList(*args):
118 """Returns an list of extents.
119
120 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700121 *args: (start_block, num_blocks) pairs defining the extents.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800122
Gilad Arnold5502b562013-03-08 13:22:31 -0800123 Returns:
124 A list of Extent objects.
Gilad Arnold5502b562013-03-08 13:22:31 -0800125 """
126 ex_list = []
127 for start_block, num_blocks in args:
128 ex_list.append(PayloadCheckerTest.NewExtent(start_block, num_blocks))
129 return ex_list
130
131 @staticmethod
132 def AddToMessage(repeated_field, field_vals):
133 for field_val in field_vals:
134 new_field = repeated_field.add()
135 new_field.CopyFrom(field_val)
136
Gilad Arnold5502b562013-03-08 13:22:31 -0800137 def SetupAddElemTest(self, is_present, is_submsg, convert=str,
138 linebreak=False, indent=0):
139 """Setup for testing of _CheckElem() and its derivatives.
140
141 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700142 is_present: Whether or not the element is found in the message.
143 is_submsg: Whether the element is a sub-message itself.
144 convert: A representation conversion function.
145 linebreak: Whether or not a linebreak is to be used in the report.
146 indent: Indentation used for the report.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800147
Gilad Arnold5502b562013-03-08 13:22:31 -0800148 Returns:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700149 msg: A mock message object.
150 report: A mock report object.
151 subreport: A mock sub-report object.
152 name: An element name to check.
153 val: Expected element value.
Gilad Arnold5502b562013-03-08 13:22:31 -0800154 """
155 name = 'foo'
156 val = 'fake submsg' if is_submsg else 'fake field'
157 subreport = 'fake subreport'
158
159 # Create a mock message.
160 msg = self.mox.CreateMock(update_metadata_pb2.message.Message)
161 msg.HasField(name).AndReturn(is_present)
162 setattr(msg, name, val)
163
164 # Create a mock report.
165 report = self.mox.CreateMock(checker._PayloadReport)
166 if is_present:
167 if is_submsg:
168 report.AddSubReport(name).AndReturn(subreport)
169 else:
170 report.AddField(name, convert(val), linebreak=linebreak, indent=indent)
171
172 self.mox.ReplayAll()
173 return (msg, report, subreport, name, val)
174
175 def DoAddElemTest(self, is_present, is_mandatory, is_submsg, convert,
176 linebreak, indent):
177 """Parametric testing of _CheckElem().
178
179 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700180 is_present: Whether or not the element is found in the message.
181 is_mandatory: Whether or not it's a mandatory element.
182 is_submsg: Whether the element is a sub-message itself.
183 convert: A representation conversion function.
184 linebreak: Whether or not a linebreak is to be used in the report.
185 indent: Indentation used for the report.
Gilad Arnold5502b562013-03-08 13:22:31 -0800186 """
187 msg, report, subreport, name, val = self.SetupAddElemTest(
188 is_present, is_submsg, convert, linebreak, indent)
189
Gilad Arnoldcb638912013-06-24 04:57:11 -0700190 args = (msg, name, report, is_mandatory, is_submsg)
191 kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
Gilad Arnold5502b562013-03-08 13:22:31 -0800192 if is_mandatory and not is_present:
193 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700194 checker.PayloadChecker._CheckElem, *args, **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -0800195 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700196 ret_val, ret_subreport = checker.PayloadChecker._CheckElem(*args,
197 **kwargs)
198 self.assertEquals(val if is_present else None, ret_val)
199 self.assertEquals(subreport if is_present and is_submsg else None,
200 ret_subreport)
Gilad Arnold5502b562013-03-08 13:22:31 -0800201
202 def DoAddFieldTest(self, is_mandatory, is_present, convert, linebreak,
203 indent):
204 """Parametric testing of _Check{Mandatory,Optional}Field().
205
206 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700207 is_mandatory: Whether we're testing a mandatory call.
208 is_present: Whether or not the element is found in the message.
209 convert: A representation conversion function.
210 linebreak: Whether or not a linebreak is to be used in the report.
211 indent: Indentation used for the report.
Gilad Arnold5502b562013-03-08 13:22:31 -0800212 """
213 msg, report, _, name, val = self.SetupAddElemTest(
214 is_present, False, convert, linebreak, indent)
215
216 # Prepare for invocation of the tested method.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700217 args = [msg, name, report]
218 kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
Gilad Arnold5502b562013-03-08 13:22:31 -0800219 if is_mandatory:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700220 args.append('bar')
Gilad Arnold5502b562013-03-08 13:22:31 -0800221 tested_func = checker.PayloadChecker._CheckMandatoryField
222 else:
223 tested_func = checker.PayloadChecker._CheckOptionalField
224
225 # Test the method call.
226 if is_mandatory and not is_present:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700227 self.assertRaises(update_payload.PayloadError, tested_func, *args,
228 **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -0800229 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700230 ret_val = tested_func(*args, **kwargs)
231 self.assertEquals(val if is_present else None, ret_val)
Gilad Arnold5502b562013-03-08 13:22:31 -0800232
233 def DoAddSubMsgTest(self, is_mandatory, is_present):
234 """Parametrized testing of _Check{Mandatory,Optional}SubMsg().
235
236 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700237 is_mandatory: Whether we're testing a mandatory call.
238 is_present: Whether or not the element is found in the message.
Gilad Arnold5502b562013-03-08 13:22:31 -0800239 """
240 msg, report, subreport, name, val = self.SetupAddElemTest(is_present, True)
241
242 # Prepare for invocation of the tested method.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700243 args = [msg, name, report]
Gilad Arnold5502b562013-03-08 13:22:31 -0800244 if is_mandatory:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700245 args.append('bar')
Gilad Arnold5502b562013-03-08 13:22:31 -0800246 tested_func = checker.PayloadChecker._CheckMandatorySubMsg
247 else:
248 tested_func = checker.PayloadChecker._CheckOptionalSubMsg
249
250 # Test the method call.
251 if is_mandatory and not is_present:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700252 self.assertRaises(update_payload.PayloadError, tested_func, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800253 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700254 ret_val, ret_subreport = tested_func(*args)
255 self.assertEquals(val if is_present else None, ret_val)
256 self.assertEquals(subreport if is_present else None, ret_subreport)
Gilad Arnold5502b562013-03-08 13:22:31 -0800257
258 def testCheckPresentIff(self):
259 """Tests _CheckPresentIff()."""
260 self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
261 None, None, 'foo', 'bar', 'baz'))
262 self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
263 'a', 'b', 'foo', 'bar', 'baz'))
264 self.assertRaises(update_payload.PayloadError,
265 checker.PayloadChecker._CheckPresentIff,
266 'a', None, 'foo', 'bar', 'baz')
267 self.assertRaises(update_payload.PayloadError,
268 checker.PayloadChecker._CheckPresentIff,
269 None, 'b', 'foo', 'bar', 'baz')
270
271 def DoCheckSha256SignatureTest(self, expect_pass, expect_subprocess_call,
272 sig_data, sig_asn1_header,
273 returned_signed_hash, expected_signed_hash):
274 """Parametric testing of _CheckSha256SignatureTest().
275
276 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700277 expect_pass: Whether or not it should pass.
278 expect_subprocess_call: Whether to expect the openssl call to happen.
279 sig_data: The signature raw data.
280 sig_asn1_header: The ASN1 header.
281 returned_signed_hash: The signed hash data retuned by openssl.
282 expected_signed_hash: The signed hash data to compare against.
Gilad Arnold5502b562013-03-08 13:22:31 -0800283 """
Gilad Arnoldcb638912013-06-24 04:57:11 -0700284 try:
285 # Stub out the subprocess invocation.
286 self.mox.StubOutWithMock(checker.PayloadChecker, '_Run')
287 if expect_subprocess_call:
288 checker.PayloadChecker._Run(
289 mox.IsA(list), send_data=sig_data).AndReturn(
290 (sig_asn1_header + returned_signed_hash, None))
Gilad Arnold5502b562013-03-08 13:22:31 -0800291
Gilad Arnoldcb638912013-06-24 04:57:11 -0700292 self.mox.ReplayAll()
293 if expect_pass:
294 self.assertIsNone(checker.PayloadChecker._CheckSha256Signature(
295 sig_data, 'foo', expected_signed_hash, 'bar'))
296 else:
297 self.assertRaises(update_payload.PayloadError,
298 checker.PayloadChecker._CheckSha256Signature,
299 sig_data, 'foo', expected_signed_hash, 'bar')
300 finally:
301 self.mox.UnsetStubs()
Gilad Arnold5502b562013-03-08 13:22:31 -0800302
303 def testCheckSha256Signature_Pass(self):
304 """Tests _CheckSha256Signature(); pass case."""
305 sig_data = 'fake-signature'.ljust(256)
306 signed_hash = hashlib.sha256('fake-data').digest()
307 self.DoCheckSha256SignatureTest(True, True, sig_data,
308 common.SIG_ASN1_HEADER, signed_hash,
309 signed_hash)
310
311 def testCheckSha256Signature_FailBadSignature(self):
312 """Tests _CheckSha256Signature(); fails due to malformed signature."""
Gilad Arnoldcb638912013-06-24 04:57:11 -0700313 sig_data = 'fake-signature' # Malformed (not 256 bytes in length).
Gilad Arnold5502b562013-03-08 13:22:31 -0800314 signed_hash = hashlib.sha256('fake-data').digest()
315 self.DoCheckSha256SignatureTest(False, False, sig_data,
316 common.SIG_ASN1_HEADER, signed_hash,
317 signed_hash)
318
319 def testCheckSha256Signature_FailBadOutputLength(self):
320 """Tests _CheckSha256Signature(); fails due to unexpected output length."""
321 sig_data = 'fake-signature'.ljust(256)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700322 signed_hash = 'fake-hash' # Malformed (not 32 bytes in length).
Gilad Arnold5502b562013-03-08 13:22:31 -0800323 self.DoCheckSha256SignatureTest(False, True, sig_data,
324 common.SIG_ASN1_HEADER, signed_hash,
325 signed_hash)
326
327 def testCheckSha256Signature_FailBadAsnHeader(self):
328 """Tests _CheckSha256Signature(); fails due to bad ASN1 header."""
329 sig_data = 'fake-signature'.ljust(256)
330 signed_hash = hashlib.sha256('fake-data').digest()
331 bad_asn1_header = 'bad-asn-header'.ljust(len(common.SIG_ASN1_HEADER))
332 self.DoCheckSha256SignatureTest(False, True, sig_data, bad_asn1_header,
333 signed_hash, signed_hash)
334
335 def testCheckSha256Signature_FailBadHash(self):
336 """Tests _CheckSha256Signature(); fails due to bad hash returned."""
337 sig_data = 'fake-signature'.ljust(256)
338 expected_signed_hash = hashlib.sha256('fake-data').digest()
339 returned_signed_hash = hashlib.sha256('bad-fake-data').digest()
340 self.DoCheckSha256SignatureTest(False, True, sig_data,
341 common.SIG_ASN1_HEADER,
342 expected_signed_hash, returned_signed_hash)
343
344 def testCheckBlocksFitLength_Pass(self):
345 """Tests _CheckBlocksFitLength(); pass case."""
346 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
347 64, 4, 16, 'foo'))
348 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
349 60, 4, 16, 'foo'))
350 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
351 49, 4, 16, 'foo'))
352 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
353 48, 3, 16, 'foo'))
354
355 def testCheckBlocksFitLength_TooManyBlocks(self):
356 """Tests _CheckBlocksFitLength(); fails due to excess blocks."""
357 self.assertRaises(update_payload.PayloadError,
358 checker.PayloadChecker._CheckBlocksFitLength,
359 64, 5, 16, 'foo')
360 self.assertRaises(update_payload.PayloadError,
361 checker.PayloadChecker._CheckBlocksFitLength,
362 60, 5, 16, 'foo')
363 self.assertRaises(update_payload.PayloadError,
364 checker.PayloadChecker._CheckBlocksFitLength,
365 49, 5, 16, 'foo')
366 self.assertRaises(update_payload.PayloadError,
367 checker.PayloadChecker._CheckBlocksFitLength,
368 48, 4, 16, 'foo')
369
370 def testCheckBlocksFitLength_TooFewBlocks(self):
371 """Tests _CheckBlocksFitLength(); fails due to insufficient blocks."""
372 self.assertRaises(update_payload.PayloadError,
373 checker.PayloadChecker._CheckBlocksFitLength,
374 64, 3, 16, 'foo')
375 self.assertRaises(update_payload.PayloadError,
376 checker.PayloadChecker._CheckBlocksFitLength,
377 60, 3, 16, 'foo')
378 self.assertRaises(update_payload.PayloadError,
379 checker.PayloadChecker._CheckBlocksFitLength,
380 49, 3, 16, 'foo')
381 self.assertRaises(update_payload.PayloadError,
382 checker.PayloadChecker._CheckBlocksFitLength,
383 48, 2, 16, 'foo')
384
385 def DoCheckManifestTest(self, fail_mismatched_block_size, fail_bad_sigs,
386 fail_mismatched_oki_ori, fail_bad_oki, fail_bad_ori,
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800387 fail_bad_nki, fail_bad_nri, fail_old_kernel_fs_size,
388 fail_old_rootfs_fs_size, fail_new_kernel_fs_size,
389 fail_new_rootfs_fs_size):
Gilad Arnold5502b562013-03-08 13:22:31 -0800390 """Parametric testing of _CheckManifest().
391
392 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700393 fail_mismatched_block_size: Simulate a missing block_size field.
394 fail_bad_sigs: Make signatures descriptor inconsistent.
395 fail_mismatched_oki_ori: Make old rootfs/kernel info partially present.
396 fail_bad_oki: Tamper with old kernel info.
397 fail_bad_ori: Tamper with old rootfs info.
398 fail_bad_nki: Tamper with new kernel info.
399 fail_bad_nri: Tamper with new rootfs info.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700400 fail_old_kernel_fs_size: Make old kernel fs size too big.
401 fail_old_rootfs_fs_size: Make old rootfs fs size too big.
402 fail_new_kernel_fs_size: Make new kernel fs size too big.
403 fail_new_rootfs_fs_size: Make new rootfs fs size too big.
Gilad Arnold5502b562013-03-08 13:22:31 -0800404 """
405 # Generate a test payload. For this test, we only care about the manifest
406 # and don't need any data blobs, hence we can use a plain paylaod generator
407 # (which also gives us more control on things that can be screwed up).
408 payload_gen = test_utils.PayloadGenerator()
409
410 # Tamper with block size, if required.
411 if fail_mismatched_block_size:
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700412 payload_gen.SetBlockSize(test_utils.KiB(1))
Gilad Arnold5502b562013-03-08 13:22:31 -0800413 else:
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700414 payload_gen.SetBlockSize(test_utils.KiB(4))
Gilad Arnold5502b562013-03-08 13:22:31 -0800415
416 # Add some operations.
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800417 payload_gen.AddOperation(False, common.OpType.MOVE,
418 src_extents=[(0, 16), (16, 497)],
419 dst_extents=[(16, 496), (0, 16)])
420 payload_gen.AddOperation(True, common.OpType.MOVE,
421 src_extents=[(0, 8), (8, 8)],
422 dst_extents=[(8, 8), (0, 8)])
Gilad Arnold5502b562013-03-08 13:22:31 -0800423
424 # Set an invalid signatures block (offset but no size), if required.
425 if fail_bad_sigs:
426 payload_gen.SetSignatures(32, None)
427
Gilad Arnold382df5c2013-05-03 12:49:28 -0700428 # Set partition / filesystem sizes.
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700429 rootfs_part_size = test_utils.MiB(8)
430 kernel_part_size = test_utils.KiB(512)
Gilad Arnold382df5c2013-05-03 12:49:28 -0700431 old_rootfs_fs_size = new_rootfs_fs_size = rootfs_part_size
432 old_kernel_fs_size = new_kernel_fs_size = kernel_part_size
433 if fail_old_kernel_fs_size:
434 old_kernel_fs_size += 100
435 if fail_old_rootfs_fs_size:
436 old_rootfs_fs_size += 100
437 if fail_new_kernel_fs_size:
438 new_kernel_fs_size += 100
439 if fail_new_rootfs_fs_size:
440 new_rootfs_fs_size += 100
441
Gilad Arnold5502b562013-03-08 13:22:31 -0800442 # Add old kernel/rootfs partition info, as required.
Gilad Arnold382df5c2013-05-03 12:49:28 -0700443 if fail_mismatched_oki_ori or fail_old_kernel_fs_size or fail_bad_oki:
Gilad Arnold5502b562013-03-08 13:22:31 -0800444 oki_hash = (None if fail_bad_oki
445 else hashlib.sha256('fake-oki-content').digest())
Gilad Arnold382df5c2013-05-03 12:49:28 -0700446 payload_gen.SetPartInfo(True, False, old_kernel_fs_size, oki_hash)
447 if not fail_mismatched_oki_ori and (fail_old_rootfs_fs_size or
448 fail_bad_ori):
449 ori_hash = (None if fail_bad_ori
450 else hashlib.sha256('fake-ori-content').digest())
451 payload_gen.SetPartInfo(False, False, old_rootfs_fs_size, ori_hash)
Gilad Arnold5502b562013-03-08 13:22:31 -0800452
453 # Add new kernel/rootfs partition info.
454 payload_gen.SetPartInfo(
Gilad Arnold382df5c2013-05-03 12:49:28 -0700455 True, True, new_kernel_fs_size,
Gilad Arnold5502b562013-03-08 13:22:31 -0800456 None if fail_bad_nki else hashlib.sha256('fake-nki-content').digest())
457 payload_gen.SetPartInfo(
Gilad Arnold382df5c2013-05-03 12:49:28 -0700458 False, True, new_rootfs_fs_size,
Gilad Arnold5502b562013-03-08 13:22:31 -0800459 None if fail_bad_nri else hashlib.sha256('fake-nri-content').digest())
460
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700461 # Set the minor version.
462 payload_gen.SetMinorVersion(0)
463
Gilad Arnold5502b562013-03-08 13:22:31 -0800464 # Create the test object.
465 payload_checker = _GetPayloadChecker(payload_gen.WriteToFile)
466 report = checker._PayloadReport()
467
468 should_fail = (fail_mismatched_block_size or fail_bad_sigs or
469 fail_mismatched_oki_ori or fail_bad_oki or fail_bad_ori or
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800470 fail_bad_nki or fail_bad_nri or fail_old_kernel_fs_size or
471 fail_old_rootfs_fs_size or fail_new_kernel_fs_size or
472 fail_new_rootfs_fs_size)
Gilad Arnold5502b562013-03-08 13:22:31 -0800473 if should_fail:
474 self.assertRaises(update_payload.PayloadError,
Gilad Arnold382df5c2013-05-03 12:49:28 -0700475 payload_checker._CheckManifest, report,
476 rootfs_part_size, kernel_part_size)
Gilad Arnold5502b562013-03-08 13:22:31 -0800477 else:
Gilad Arnold382df5c2013-05-03 12:49:28 -0700478 self.assertIsNone(payload_checker._CheckManifest(report,
479 rootfs_part_size,
480 kernel_part_size))
Gilad Arnold5502b562013-03-08 13:22:31 -0800481
482 def testCheckLength(self):
483 """Tests _CheckLength()."""
484 payload_checker = checker.PayloadChecker(self.MockPayload())
485 block_size = payload_checker.block_size
486
487 # Passes.
488 self.assertIsNone(payload_checker._CheckLength(
489 int(3.5 * block_size), 4, 'foo', 'bar'))
490 # Fails, too few blocks.
491 self.assertRaises(update_payload.PayloadError,
492 payload_checker._CheckLength,
493 int(3.5 * block_size), 3, 'foo', 'bar')
494 # Fails, too many blocks.
495 self.assertRaises(update_payload.PayloadError,
496 payload_checker._CheckLength,
497 int(3.5 * block_size), 5, 'foo', 'bar')
498
499 def testCheckExtents(self):
500 """Tests _CheckExtents()."""
501 payload_checker = checker.PayloadChecker(self.MockPayload())
502 block_size = payload_checker.block_size
503
504 # Passes w/ all real extents.
505 extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
506 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700507 23,
Gilad Arnold5502b562013-03-08 13:22:31 -0800508 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700509 collections.defaultdict(int), 'foo'))
Gilad Arnold5502b562013-03-08 13:22:31 -0800510
511 # Passes w/ pseudo-extents (aka sparse holes).
512 extents = self.NewExtentList((0, 4), (common.PSEUDO_EXTENT_MARKER, 5),
513 (8, 3))
514 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700515 12,
Gilad Arnold5502b562013-03-08 13:22:31 -0800516 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
517 collections.defaultdict(int), 'foo',
Gilad Arnoldcb638912013-06-24 04:57:11 -0700518 allow_pseudo=True))
Gilad Arnold5502b562013-03-08 13:22:31 -0800519
520 # Passes w/ pseudo-extent due to a signature.
521 extents = self.NewExtentList((common.PSEUDO_EXTENT_MARKER, 2))
522 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700523 2,
Gilad Arnold5502b562013-03-08 13:22:31 -0800524 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
525 collections.defaultdict(int), 'foo',
Gilad Arnoldcb638912013-06-24 04:57:11 -0700526 allow_signature=True))
Gilad Arnold5502b562013-03-08 13:22:31 -0800527
528 # Fails, extent missing a start block.
529 extents = self.NewExtentList((-1, 4), (8, 3), (1024, 16))
530 self.assertRaises(
531 update_payload.PayloadError, payload_checker._CheckExtents,
532 extents, (1024 + 16) * block_size, collections.defaultdict(int),
533 'foo')
534
535 # Fails, extent missing block count.
536 extents = self.NewExtentList((0, -1), (8, 3), (1024, 16))
537 self.assertRaises(
538 update_payload.PayloadError, payload_checker._CheckExtents,
539 extents, (1024 + 16) * block_size, collections.defaultdict(int),
540 'foo')
541
542 # Fails, extent has zero blocks.
543 extents = self.NewExtentList((0, 4), (8, 3), (1024, 0))
544 self.assertRaises(
545 update_payload.PayloadError, payload_checker._CheckExtents,
546 extents, (1024 + 16) * block_size, collections.defaultdict(int),
547 'foo')
548
549 # Fails, extent exceeds partition boundaries.
550 extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
551 self.assertRaises(
552 update_payload.PayloadError, payload_checker._CheckExtents,
553 extents, (1024 + 15) * block_size, collections.defaultdict(int),
554 'foo')
555
556 def testCheckReplaceOperation(self):
557 """Tests _CheckReplaceOperation() where op.type == REPLACE."""
558 payload_checker = checker.PayloadChecker(self.MockPayload())
559 block_size = payload_checker.block_size
560 data_length = 10000
561
562 op = self.mox.CreateMock(
563 update_metadata_pb2.DeltaArchiveManifest.InstallOperation)
564 op.type = common.OpType.REPLACE
565
566 # Pass.
567 op.src_extents = []
568 self.assertIsNone(
569 payload_checker._CheckReplaceOperation(
570 op, data_length, (data_length + block_size - 1) / block_size,
571 'foo'))
572
573 # Fail, src extents founds.
574 op.src_extents = ['bar']
575 self.assertRaises(
576 update_payload.PayloadError,
577 payload_checker._CheckReplaceOperation,
578 op, data_length, (data_length + block_size - 1) / block_size, 'foo')
579
580 # Fail, missing data.
581 op.src_extents = []
582 self.assertRaises(
583 update_payload.PayloadError,
584 payload_checker._CheckReplaceOperation,
585 op, None, (data_length + block_size - 1) / block_size, 'foo')
586
587 # Fail, length / block number mismatch.
588 op.src_extents = ['bar']
589 self.assertRaises(
590 update_payload.PayloadError,
591 payload_checker._CheckReplaceOperation,
592 op, data_length, (data_length + block_size - 1) / block_size + 1, 'foo')
593
594 def testCheckReplaceBzOperation(self):
595 """Tests _CheckReplaceOperation() where op.type == REPLACE_BZ."""
596 payload_checker = checker.PayloadChecker(self.MockPayload())
597 block_size = payload_checker.block_size
598 data_length = block_size * 3
599
600 op = self.mox.CreateMock(
601 update_metadata_pb2.DeltaArchiveManifest.InstallOperation)
602 op.type = common.OpType.REPLACE_BZ
603
604 # Pass.
605 op.src_extents = []
606 self.assertIsNone(
607 payload_checker._CheckReplaceOperation(
608 op, data_length, (data_length + block_size - 1) / block_size + 5,
609 'foo'))
610
611 # Fail, src extents founds.
612 op.src_extents = ['bar']
613 self.assertRaises(
614 update_payload.PayloadError,
615 payload_checker._CheckReplaceOperation,
616 op, data_length, (data_length + block_size - 1) / block_size + 5, 'foo')
617
618 # Fail, missing data.
619 op.src_extents = []
620 self.assertRaises(
621 update_payload.PayloadError,
622 payload_checker._CheckReplaceOperation,
623 op, None, (data_length + block_size - 1) / block_size, 'foo')
624
625 # Fail, too few blocks to justify BZ.
626 op.src_extents = []
627 self.assertRaises(
628 update_payload.PayloadError,
629 payload_checker._CheckReplaceOperation,
630 op, data_length, (data_length + block_size - 1) / block_size, 'foo')
631
632 def testCheckMoveOperation_Pass(self):
633 """Tests _CheckMoveOperation(); pass case."""
634 payload_checker = checker.PayloadChecker(self.MockPayload())
635 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
636 op.type = common.OpType.MOVE
637
638 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700639 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800640 self.AddToMessage(op.dst_extents,
641 self.NewExtentList((16, 128), (512, 6)))
642 self.assertIsNone(
643 payload_checker._CheckMoveOperation(op, None, 134, 134, 'foo'))
644
645 def testCheckMoveOperation_FailContainsData(self):
646 """Tests _CheckMoveOperation(); fails, message contains data."""
647 payload_checker = checker.PayloadChecker(self.MockPayload())
648 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
649 op.type = common.OpType.MOVE
650
651 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700652 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800653 self.AddToMessage(op.dst_extents,
654 self.NewExtentList((16, 128), (512, 6)))
655 self.assertRaises(
656 update_payload.PayloadError,
657 payload_checker._CheckMoveOperation,
658 op, 1024, 134, 134, 'foo')
659
660 def testCheckMoveOperation_FailInsufficientSrcBlocks(self):
661 """Tests _CheckMoveOperation(); fails, not enough actual src blocks."""
662 payload_checker = checker.PayloadChecker(self.MockPayload())
663 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
664 op.type = common.OpType.MOVE
665
666 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700667 self.NewExtentList((1, 4), (12, 2), (1024, 127)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800668 self.AddToMessage(op.dst_extents,
669 self.NewExtentList((16, 128), (512, 6)))
670 self.assertRaises(
671 update_payload.PayloadError,
672 payload_checker._CheckMoveOperation,
673 op, None, 134, 134, 'foo')
674
675 def testCheckMoveOperation_FailInsufficientDstBlocks(self):
676 """Tests _CheckMoveOperation(); fails, not enough actual dst blocks."""
677 payload_checker = checker.PayloadChecker(self.MockPayload())
678 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
679 op.type = common.OpType.MOVE
680
681 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700682 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800683 self.AddToMessage(op.dst_extents,
684 self.NewExtentList((16, 128), (512, 5)))
685 self.assertRaises(
686 update_payload.PayloadError,
687 payload_checker._CheckMoveOperation,
688 op, None, 134, 134, 'foo')
689
690 def testCheckMoveOperation_FailExcessSrcBlocks(self):
691 """Tests _CheckMoveOperation(); fails, too many actual src blocks."""
692 payload_checker = checker.PayloadChecker(self.MockPayload())
693 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
694 op.type = common.OpType.MOVE
695
696 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700697 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800698 self.AddToMessage(op.dst_extents,
699 self.NewExtentList((16, 128), (512, 5)))
700 self.assertRaises(
701 update_payload.PayloadError,
702 payload_checker._CheckMoveOperation,
703 op, None, 134, 134, 'foo')
704 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700705 self.NewExtentList((1, 4), (12, 2), (1024, 129)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800706 self.AddToMessage(op.dst_extents,
707 self.NewExtentList((16, 128), (512, 6)))
708 self.assertRaises(
709 update_payload.PayloadError,
710 payload_checker._CheckMoveOperation,
711 op, None, 134, 134, 'foo')
712
713 def testCheckMoveOperation_FailExcessDstBlocks(self):
714 """Tests _CheckMoveOperation(); fails, too many actual dst blocks."""
715 payload_checker = checker.PayloadChecker(self.MockPayload())
716 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
717 op.type = common.OpType.MOVE
718
719 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700720 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800721 self.AddToMessage(op.dst_extents,
722 self.NewExtentList((16, 128), (512, 7)))
723 self.assertRaises(
724 update_payload.PayloadError,
725 payload_checker._CheckMoveOperation,
726 op, None, 134, 134, 'foo')
727
728 def testCheckMoveOperation_FailStagnantBlocks(self):
729 """Tests _CheckMoveOperation(); fails, there are blocks that do not move."""
730 payload_checker = checker.PayloadChecker(self.MockPayload())
731 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
732 op.type = common.OpType.MOVE
733
734 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700735 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
736 self.AddToMessage(op.dst_extents,
737 self.NewExtentList((8, 128), (512, 6)))
738 self.assertRaises(
739 update_payload.PayloadError,
740 payload_checker._CheckMoveOperation,
741 op, None, 134, 134, 'foo')
742
743 def testCheckMoveOperation_FailZeroStartBlock(self):
744 """Tests _CheckMoveOperation(); fails, has extent with start block 0."""
745 payload_checker = checker.PayloadChecker(self.MockPayload())
746 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
747 op.type = common.OpType.MOVE
748
749 self.AddToMessage(op.src_extents,
Gilad Arnold5502b562013-03-08 13:22:31 -0800750 self.NewExtentList((0, 4), (12, 2), (1024, 128)))
751 self.AddToMessage(op.dst_extents,
752 self.NewExtentList((8, 128), (512, 6)))
753 self.assertRaises(
754 update_payload.PayloadError,
755 payload_checker._CheckMoveOperation,
756 op, None, 134, 134, 'foo')
757
Allie Woodb065e132015-04-24 10:20:27 -0700758 self.AddToMessage(op.src_extents,
759 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
760 self.AddToMessage(op.dst_extents,
761 self.NewExtentList((0, 128), (512, 6)))
762 self.assertRaises(
763 update_payload.PayloadError,
764 payload_checker._CheckMoveOperation,
765 op, None, 134, 134, 'foo')
766
Gilad Arnold5502b562013-03-08 13:22:31 -0800767 def testCheckBsdiff(self):
768 """Tests _CheckMoveOperation()."""
769 payload_checker = checker.PayloadChecker(self.MockPayload())
770
771 # Pass.
772 self.assertIsNone(
773 payload_checker._CheckBsdiffOperation(10000, 3, 'foo'))
774
775 # Fail, missing data blob.
776 self.assertRaises(
777 update_payload.PayloadError,
778 payload_checker._CheckBsdiffOperation,
779 None, 3, 'foo')
780
781 # Fail, too big of a diff blob (unjustified).
782 self.assertRaises(
783 update_payload.PayloadError,
784 payload_checker._CheckBsdiffOperation,
785 10000, 2, 'foo')
786
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800787 def testCheckSourceCopyOperation_Pass(self):
788 """Tests _CheckSourceCopyOperation(); pass case."""
789 payload_checker = checker.PayloadChecker(self.MockPayload())
790 self.assertIsNone(
791 payload_checker._CheckSourceCopyOperation(None, 134, 134, 'foo'))
792
793 def testCheckSourceCopyOperation_FailContainsData(self):
794 """Tests _CheckSourceCopyOperation(); message contains data."""
795 payload_checker = checker.PayloadChecker(self.MockPayload())
796 self.assertRaises(update_payload.PayloadError,
797 payload_checker._CheckSourceCopyOperation,
798 134, 0, 0, 'foo')
799
800 def testCheckSourceCopyOperation_FailBlockCountsMismatch(self):
801 """Tests _CheckSourceCopyOperation(); src and dst block totals not equal."""
802 payload_checker = checker.PayloadChecker(self.MockPayload())
803 self.assertRaises(update_payload.PayloadError,
804 payload_checker._CheckSourceCopyOperation,
805 None, 0, 1, 'foo')
806
Gilad Arnold5502b562013-03-08 13:22:31 -0800807 def DoCheckOperationTest(self, op_type_name, is_last, allow_signature,
808 allow_unhashed, fail_src_extents, fail_dst_extents,
809 fail_mismatched_data_offset_length,
810 fail_missing_dst_extents, fail_src_length,
811 fail_dst_length, fail_data_hash,
Allie Wood7cf9f132015-02-26 14:28:19 -0800812 fail_prev_data_offset, fail_bad_minor_version):
Gilad Arnold5502b562013-03-08 13:22:31 -0800813 """Parametric testing of _CheckOperation().
814
815 Args:
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800816 op_type_name: 'REPLACE', 'REPLACE_BZ', 'MOVE', 'BSDIFF', 'SOURCE_COPY',
817 or 'SOURCE_BSDIFF'.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700818 is_last: Whether we're testing the last operation in a sequence.
819 allow_signature: Whether we're testing a signature-capable operation.
820 allow_unhashed: Whether we're allowing to not hash the data.
821 fail_src_extents: Tamper with src extents.
822 fail_dst_extents: Tamper with dst extents.
823 fail_mismatched_data_offset_length: Make data_{offset,length}
824 inconsistent.
825 fail_missing_dst_extents: Do not include dst extents.
826 fail_src_length: Make src length inconsistent.
827 fail_dst_length: Make dst length inconsistent.
828 fail_data_hash: Tamper with the data blob hash.
829 fail_prev_data_offset: Make data space uses incontiguous.
Allie Wood7cf9f132015-02-26 14:28:19 -0800830 fail_bad_minor_version: Make minor version incompatible with op.
Gilad Arnold5502b562013-03-08 13:22:31 -0800831 """
832 op_type = _OpTypeByName(op_type_name)
833
834 # Create the test object.
835 payload = self.MockPayload()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -0700836 payload_checker = checker.PayloadChecker(payload,
837 allow_unhashed=allow_unhashed)
Gilad Arnold5502b562013-03-08 13:22:31 -0800838 block_size = payload_checker.block_size
839
840 # Create auxiliary arguments.
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700841 old_part_size = test_utils.MiB(4)
842 new_part_size = test_utils.MiB(8)
Gilad Arnold5502b562013-03-08 13:22:31 -0800843 old_block_counters = array.array(
844 'B', [0] * ((old_part_size + block_size - 1) / block_size))
845 new_block_counters = array.array(
846 'B', [0] * ((new_part_size + block_size - 1) / block_size))
847 prev_data_offset = 1876
848 blob_hash_counts = collections.defaultdict(int)
849
850 # Create the operation object for the test.
851 op = update_metadata_pb2.DeltaArchiveManifest.InstallOperation()
852 op.type = op_type
853
854 total_src_blocks = 0
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800855 if op_type in (common.OpType.MOVE, common.OpType.BSDIFF,
856 common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
Gilad Arnold5502b562013-03-08 13:22:31 -0800857 if fail_src_extents:
858 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700859 self.NewExtentList((1, 0)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800860 else:
861 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700862 self.NewExtentList((1, 16)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800863 total_src_blocks = 16
864
Allie Wood7cf9f132015-02-26 14:28:19 -0800865 if op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700866 payload_checker.minor_version = 0
Allie Wood7cf9f132015-02-26 14:28:19 -0800867 elif op_type in (common.OpType.MOVE, common.OpType.BSDIFF):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700868 payload_checker.minor_version = 2 if fail_bad_minor_version else 1
Allie Wood7cf9f132015-02-26 14:28:19 -0800869 elif op_type in (common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700870 payload_checker.minor_version = 1 if fail_bad_minor_version else 2
Allie Wood7cf9f132015-02-26 14:28:19 -0800871
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800872 if op_type not in (common.OpType.MOVE, common.OpType.SOURCE_COPY):
Gilad Arnold5502b562013-03-08 13:22:31 -0800873 if not fail_mismatched_data_offset_length:
874 op.data_length = 16 * block_size - 8
875 if fail_prev_data_offset:
876 op.data_offset = prev_data_offset + 16
877 else:
878 op.data_offset = prev_data_offset
879
880 fake_data = 'fake-data'.ljust(op.data_length)
881 if not (allow_unhashed or (is_last and allow_signature and
882 op_type == common.OpType.REPLACE)):
883 if not fail_data_hash:
884 # Create a valid data blob hash.
885 op.data_sha256_hash = hashlib.sha256(fake_data).digest()
886 payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
887 fake_data)
888 elif fail_data_hash:
889 # Create an invalid data blob hash.
890 op.data_sha256_hash = hashlib.sha256(
891 fake_data.replace(' ', '-')).digest()
892 payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
893 fake_data)
894
895 total_dst_blocks = 0
896 if not fail_missing_dst_extents:
897 total_dst_blocks = 16
898 if fail_dst_extents:
899 self.AddToMessage(op.dst_extents,
900 self.NewExtentList((4, 16), (32, 0)))
901 else:
902 self.AddToMessage(op.dst_extents,
903 self.NewExtentList((4, 8), (64, 8)))
904
905 if total_src_blocks:
906 if fail_src_length:
907 op.src_length = total_src_blocks * block_size + 8
908 else:
909 op.src_length = total_src_blocks * block_size
910 elif fail_src_length:
911 # Add an orphaned src_length.
912 op.src_length = 16
913
914 if total_dst_blocks:
915 if fail_dst_length:
916 op.dst_length = total_dst_blocks * block_size + 8
917 else:
918 op.dst_length = total_dst_blocks * block_size
919
920 self.mox.ReplayAll()
921 should_fail = (fail_src_extents or fail_dst_extents or
922 fail_mismatched_data_offset_length or
923 fail_missing_dst_extents or fail_src_length or
Allie Wood7cf9f132015-02-26 14:28:19 -0800924 fail_dst_length or fail_data_hash or fail_prev_data_offset or
925 fail_bad_minor_version)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700926 args = (op, 'foo', is_last, old_block_counters, new_block_counters,
927 old_part_size, new_part_size, prev_data_offset, allow_signature,
928 blob_hash_counts)
Gilad Arnold5502b562013-03-08 13:22:31 -0800929 if should_fail:
930 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700931 payload_checker._CheckOperation, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800932 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700933 self.assertEqual(op.data_length if op.HasField('data_length') else 0,
934 payload_checker._CheckOperation(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -0800935
936 def testAllocBlockCounters(self):
937 """Tests _CheckMoveOperation()."""
938 payload_checker = checker.PayloadChecker(self.MockPayload())
939 block_size = payload_checker.block_size
940
941 # Check allocation for block-aligned partition size, ensure it's integers.
942 result = payload_checker._AllocBlockCounters(16 * block_size)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700943 self.assertEqual(16, len(result))
944 self.assertEqual(int, type(result[0]))
Gilad Arnold5502b562013-03-08 13:22:31 -0800945
946 # Check allocation of unaligned partition sizes.
947 result = payload_checker._AllocBlockCounters(16 * block_size - 1)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700948 self.assertEqual(16, len(result))
Gilad Arnold5502b562013-03-08 13:22:31 -0800949 result = payload_checker._AllocBlockCounters(16 * block_size + 1)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700950 self.assertEqual(17, len(result))
Gilad Arnold5502b562013-03-08 13:22:31 -0800951
Allie Woodfb04d302015-04-03 14:25:48 -0700952 def DoCheckOperationsTest(self, fail_nonexhaustive_full_update):
Gilad Arnold5502b562013-03-08 13:22:31 -0800953 # Generate a test payload. For this test, we only care about one
954 # (arbitrary) set of operations, so we'll only be generating kernel and
955 # test with them.
956 payload_gen = test_utils.PayloadGenerator()
957
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700958 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -0800959 payload_gen.SetBlockSize(block_size)
960
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700961 rootfs_part_size = test_utils.MiB(8)
Gilad Arnold5502b562013-03-08 13:22:31 -0800962
963 # Fake rootfs operations in a full update, tampered with as required.
964 rootfs_op_type = common.OpType.REPLACE
Gilad Arnold5502b562013-03-08 13:22:31 -0800965 rootfs_data_length = rootfs_part_size
966 if fail_nonexhaustive_full_update:
967 rootfs_data_length -= block_size
968
969 payload_gen.AddOperation(False, rootfs_op_type,
970 dst_extents=[(0, rootfs_data_length / block_size)],
971 data_offset=0,
972 data_length=rootfs_data_length)
973
974 # Create the test object.
Gilad Arnoldeaed0d12013-04-30 15:38:22 -0700975 payload_checker = _GetPayloadChecker(payload_gen.WriteToFile,
976 checker_init_dargs={
977 'allow_unhashed': True})
Gilad Arnold5502b562013-03-08 13:22:31 -0800978 payload_checker.payload_type = checker._TYPE_FULL
979 report = checker._PayloadReport()
980
Gilad Arnoldcb638912013-06-24 04:57:11 -0700981 args = (payload_checker.payload.manifest.install_operations, report,
982 'foo', 0, rootfs_part_size, rootfs_part_size, 0, False)
Allie Woodfb04d302015-04-03 14:25:48 -0700983 if fail_nonexhaustive_full_update:
Gilad Arnold5502b562013-03-08 13:22:31 -0800984 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700985 payload_checker._CheckOperations, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800986 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700987 self.assertEqual(rootfs_data_length,
988 payload_checker._CheckOperations(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -0800989
990 def DoCheckSignaturesTest(self, fail_empty_sigs_blob, fail_missing_pseudo_op,
991 fail_mismatched_pseudo_op, fail_sig_missing_fields,
992 fail_unknown_sig_version, fail_incorrect_sig):
993 # Generate a test payload. For this test, we only care about the signature
994 # block and how it relates to the payload hash. Therefore, we're generating
995 # a random (otherwise useless) payload for this purpose.
996 payload_gen = test_utils.EnhancedPayloadGenerator()
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700997 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -0800998 payload_gen.SetBlockSize(block_size)
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700999 rootfs_part_size = test_utils.MiB(2)
1000 kernel_part_size = test_utils.KiB(16)
Gilad Arnold5502b562013-03-08 13:22:31 -08001001 payload_gen.SetPartInfo(False, True, rootfs_part_size,
1002 hashlib.sha256('fake-new-rootfs-content').digest())
Gilad Arnold382df5c2013-05-03 12:49:28 -07001003 payload_gen.SetPartInfo(True, True, kernel_part_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001004 hashlib.sha256('fake-new-kernel-content').digest())
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001005 payload_gen.SetMinorVersion(0)
Gilad Arnold5502b562013-03-08 13:22:31 -08001006 payload_gen.AddOperationWithData(
1007 False, common.OpType.REPLACE,
1008 dst_extents=[(0, rootfs_part_size / block_size)],
1009 data_blob=os.urandom(rootfs_part_size))
1010
1011 do_forge_pseudo_op = (fail_missing_pseudo_op or fail_mismatched_pseudo_op)
1012 do_forge_sigs_data = (do_forge_pseudo_op or fail_empty_sigs_blob or
1013 fail_sig_missing_fields or fail_unknown_sig_version
1014 or fail_incorrect_sig)
1015
1016 sigs_data = None
1017 if do_forge_sigs_data:
1018 sigs_gen = test_utils.SignaturesGenerator()
1019 if not fail_empty_sigs_blob:
1020 if fail_sig_missing_fields:
1021 sig_data = None
1022 else:
1023 sig_data = test_utils.SignSha256('fake-payload-content',
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001024 test_utils._PRIVKEY_FILE_NAME)
Gilad Arnold5502b562013-03-08 13:22:31 -08001025 sigs_gen.AddSig(5 if fail_unknown_sig_version else 1, sig_data)
1026
1027 sigs_data = sigs_gen.ToBinary()
1028 payload_gen.SetSignatures(payload_gen.curr_offset, len(sigs_data))
1029
1030 if do_forge_pseudo_op:
1031 assert sigs_data is not None, 'should have forged signatures blob by now'
1032 sigs_len = len(sigs_data)
1033 payload_gen.AddOperation(
1034 False, common.OpType.REPLACE,
1035 data_offset=payload_gen.curr_offset / 2,
1036 data_length=sigs_len / 2,
1037 dst_extents=[(0, (sigs_len / 2 + block_size - 1) / block_size)])
1038
1039 # Generate payload (complete w/ signature) and create the test object.
1040 payload_checker = _GetPayloadChecker(
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001041 payload_gen.WriteToFileWithData,
1042 payload_gen_dargs={
1043 'sigs_data': sigs_data,
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001044 'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001045 'do_add_pseudo_operation': not do_forge_pseudo_op})
Gilad Arnold5502b562013-03-08 13:22:31 -08001046 payload_checker.payload_type = checker._TYPE_FULL
1047 report = checker._PayloadReport()
1048
1049 # We have to check the manifest first in order to set signature attributes.
Gilad Arnold382df5c2013-05-03 12:49:28 -07001050 payload_checker._CheckManifest(report, rootfs_part_size, kernel_part_size)
Gilad Arnold5502b562013-03-08 13:22:31 -08001051
1052 should_fail = (fail_empty_sigs_blob or fail_missing_pseudo_op or
1053 fail_mismatched_pseudo_op or fail_sig_missing_fields or
1054 fail_unknown_sig_version or fail_incorrect_sig)
Gilad Arnoldcb638912013-06-24 04:57:11 -07001055 args = (report, test_utils._PUBKEY_FILE_NAME)
Gilad Arnold5502b562013-03-08 13:22:31 -08001056 if should_fail:
1057 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001058 payload_checker._CheckSignatures, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -08001059 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001060 self.assertIsNone(payload_checker._CheckSignatures(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -08001061
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001062 def DoCheckManifestMinorVersionTest(self, minor_version, payload_type):
1063 """Parametric testing for CheckManifestMinorVersion().
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001064
1065 Args:
1066 minor_version: The payload minor version to test with.
1067 payload_type: The type of the payload we're testing, delta or full.
1068 """
1069 # Create the test object.
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001070 payload = self.MockPayload()
1071 payload.manifest.minor_version = minor_version
1072 payload_checker = checker.PayloadChecker(payload)
1073 payload_checker.payload_type = payload_type
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001074 report = checker._PayloadReport()
1075
1076 should_succeed = (
1077 (minor_version == 0 and payload_type == checker._TYPE_FULL) or
1078 (minor_version == 1 and payload_type == checker._TYPE_DELTA) or
1079 (minor_version == 2 and payload_type == checker._TYPE_DELTA))
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001080 args = (report,)
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001081
1082 if should_succeed:
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001083 self.assertIsNone(payload_checker._CheckManifestMinorVersion(*args))
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001084 else:
1085 self.assertRaises(update_payload.PayloadError,
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001086 payload_checker._CheckManifestMinorVersion, *args)
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001087
Gilad Arnold06eea332015-07-13 18:06:33 -07001088 def DoRunTest(self, rootfs_part_size_provided, kernel_part_size_provided,
1089 fail_wrong_payload_type, fail_invalid_block_size,
1090 fail_mismatched_block_size, fail_excess_data,
1091 fail_rootfs_part_size_exceeded,
1092 fail_kernel_part_size_exceeded):
Gilad Arnold5502b562013-03-08 13:22:31 -08001093 # Generate a test payload. For this test, we generate a full update that
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001094 # has sample kernel and rootfs operations. Since most testing is done with
Gilad Arnold5502b562013-03-08 13:22:31 -08001095 # internal PayloadChecker methods that are tested elsewhere, here we only
1096 # tamper with what's actually being manipulated and/or tested in the Run()
1097 # method itself. Note that the checker doesn't verify partition hashes, so
1098 # they're safe to fake.
1099 payload_gen = test_utils.EnhancedPayloadGenerator()
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001100 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -08001101 payload_gen.SetBlockSize(block_size)
Gilad Arnold06eea332015-07-13 18:06:33 -07001102 kernel_filesystem_size = test_utils.KiB(16)
1103 rootfs_filesystem_size = test_utils.MiB(2)
1104 payload_gen.SetPartInfo(False, True, rootfs_filesystem_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001105 hashlib.sha256('fake-new-rootfs-content').digest())
Gilad Arnold06eea332015-07-13 18:06:33 -07001106 payload_gen.SetPartInfo(True, True, kernel_filesystem_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001107 hashlib.sha256('fake-new-kernel-content').digest())
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001108 payload_gen.SetMinorVersion(0)
Gilad Arnold06eea332015-07-13 18:06:33 -07001109
1110 rootfs_part_size = 0
1111 if rootfs_part_size_provided:
1112 rootfs_part_size = rootfs_filesystem_size + block_size
1113 rootfs_op_size = rootfs_part_size or rootfs_filesystem_size
1114 if fail_rootfs_part_size_exceeded:
1115 rootfs_op_size += block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001116 payload_gen.AddOperationWithData(
1117 False, common.OpType.REPLACE,
Gilad Arnold06eea332015-07-13 18:06:33 -07001118 dst_extents=[(0, rootfs_op_size / block_size)],
1119 data_blob=os.urandom(rootfs_op_size))
1120
1121 kernel_part_size = 0
1122 if kernel_part_size_provided:
1123 kernel_part_size = kernel_filesystem_size + block_size
1124 kernel_op_size = kernel_part_size or kernel_filesystem_size
1125 if fail_kernel_part_size_exceeded:
1126 kernel_op_size += block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001127 payload_gen.AddOperationWithData(
1128 True, common.OpType.REPLACE,
Gilad Arnold06eea332015-07-13 18:06:33 -07001129 dst_extents=[(0, kernel_op_size / block_size)],
1130 data_blob=os.urandom(kernel_op_size))
Gilad Arnold5502b562013-03-08 13:22:31 -08001131
1132 # Generate payload (complete w/ signature) and create the test object.
Gilad Arnold5502b562013-03-08 13:22:31 -08001133 if fail_invalid_block_size:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001134 use_block_size = block_size + 5 # Not a power of two.
Gilad Arnold5502b562013-03-08 13:22:31 -08001135 elif fail_mismatched_block_size:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001136 use_block_size = block_size * 2 # Different that payload stated.
Gilad Arnold5502b562013-03-08 13:22:31 -08001137 else:
1138 use_block_size = block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001139
Gilad Arnoldcb638912013-06-24 04:57:11 -07001140 kwargs = {
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001141 'payload_gen_dargs': {
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001142 'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001143 'do_add_pseudo_operation': True,
1144 'is_pseudo_in_kernel': True,
1145 'padding': os.urandom(1024) if fail_excess_data else None},
1146 'checker_init_dargs': {
1147 'assert_type': 'delta' if fail_wrong_payload_type else 'full',
1148 'block_size': use_block_size}}
1149 if fail_invalid_block_size:
1150 self.assertRaises(update_payload.PayloadError, _GetPayloadChecker,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001151 payload_gen.WriteToFileWithData, **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -08001152 else:
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001153 payload_checker = _GetPayloadChecker(payload_gen.WriteToFileWithData,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001154 **kwargs)
Gilad Arnold06eea332015-07-13 18:06:33 -07001155
1156 kwargs = {'pubkey_file_name': test_utils._PUBKEY_FILE_NAME,
1157 'rootfs_part_size': rootfs_part_size,
1158 'kernel_part_size': kernel_part_size}
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001159 should_fail = (fail_wrong_payload_type or fail_mismatched_block_size or
Gilad Arnold06eea332015-07-13 18:06:33 -07001160 fail_excess_data or
1161 fail_rootfs_part_size_exceeded or
1162 fail_kernel_part_size_exceeded)
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001163 if should_fail:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001164 self.assertRaises(update_payload.PayloadError, payload_checker.Run,
1165 **kwargs)
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001166 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001167 self.assertIsNone(payload_checker.Run(**kwargs))
Gilad Arnold5502b562013-03-08 13:22:31 -08001168
Gilad Arnold5502b562013-03-08 13:22:31 -08001169# This implements a generic API, hence the occasional unused args.
1170# pylint: disable=W0613
1171def ValidateCheckOperationTest(op_type_name, is_last, allow_signature,
1172 allow_unhashed, fail_src_extents,
1173 fail_dst_extents,
1174 fail_mismatched_data_offset_length,
1175 fail_missing_dst_extents, fail_src_length,
1176 fail_dst_length, fail_data_hash,
Allie Wood7cf9f132015-02-26 14:28:19 -08001177 fail_prev_data_offset, fail_bad_minor_version):
Gilad Arnold5502b562013-03-08 13:22:31 -08001178 """Returns True iff the combination of arguments represents a valid test."""
1179 op_type = _OpTypeByName(op_type_name)
1180
Allie Wood7cf9f132015-02-26 14:28:19 -08001181 # REPLACE/REPLACE_BZ operations don't read data from src partition. They are
1182 # compatible with all valid minor versions, so we don't need to check that.
Gilad Arnold5502b562013-03-08 13:22:31 -08001183 if (op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ) and (
Allie Wood7cf9f132015-02-26 14:28:19 -08001184 fail_src_extents or fail_src_length or fail_bad_minor_version)):
Gilad Arnold5502b562013-03-08 13:22:31 -08001185 return False
1186
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001187 # MOVE and SOURCE_COPY operations don't carry data.
1188 if (op_type in (common.OpType.MOVE, common.OpType.SOURCE_COPY) and (
Gilad Arnold5502b562013-03-08 13:22:31 -08001189 fail_mismatched_data_offset_length or fail_data_hash or
1190 fail_prev_data_offset)):
1191 return False
1192
1193 return True
1194
1195
1196def TestMethodBody(run_method_name, run_dargs):
1197 """Returns a function that invokes a named method with named arguments."""
1198 return lambda self: getattr(self, run_method_name)(**run_dargs)
1199
1200
1201def AddParametricTests(tested_method_name, arg_space, validate_func=None):
1202 """Enumerates and adds specific parametric tests to PayloadCheckerTest.
1203
1204 This function enumerates a space of test parameters (defined by arg_space),
1205 then binds a new, unique method name in PayloadCheckerTest to a test function
1206 that gets handed the said parameters. This is a preferable approach to doing
1207 the enumeration and invocation during the tests because this way each test is
1208 treated as a complete run by the unittest framework, and so benefits from the
1209 usual setUp/tearDown mechanics.
1210
1211 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001212 tested_method_name: Name of the tested PayloadChecker method.
1213 arg_space: A dictionary containing variables (keys) and lists of values
1214 (values) associated with them.
1215 validate_func: A function used for validating test argument combinations.
Gilad Arnold5502b562013-03-08 13:22:31 -08001216 """
1217 for value_tuple in itertools.product(*arg_space.itervalues()):
1218 run_dargs = dict(zip(arg_space.iterkeys(), value_tuple))
1219 if validate_func and not validate_func(**run_dargs):
1220 continue
1221 run_method_name = 'Do%sTest' % tested_method_name
1222 test_method_name = 'test%s' % tested_method_name
1223 for arg_key, arg_val in run_dargs.iteritems():
1224 if arg_val or type(arg_val) is int:
1225 test_method_name += '__%s=%s' % (arg_key, arg_val)
1226 setattr(PayloadCheckerTest, test_method_name,
1227 TestMethodBody(run_method_name, run_dargs))
1228
1229
1230def AddAllParametricTests():
1231 """Enumerates and adds all parametric tests to PayloadCheckerTest."""
1232 # Add all _CheckElem() test cases.
1233 AddParametricTests('AddElem',
1234 {'linebreak': (True, False),
1235 'indent': (0, 1, 2),
1236 'convert': (str, lambda s: s[::-1]),
1237 'is_present': (True, False),
1238 'is_mandatory': (True, False),
1239 'is_submsg': (True, False)})
1240
1241 # Add all _Add{Mandatory,Optional}Field tests.
1242 AddParametricTests('AddField',
1243 {'is_mandatory': (True, False),
1244 'linebreak': (True, False),
1245 'indent': (0, 1, 2),
1246 'convert': (str, lambda s: s[::-1]),
1247 'is_present': (True, False)})
1248
1249 # Add all _Add{Mandatory,Optional}SubMsg tests.
1250 AddParametricTests('AddSubMsg',
1251 {'is_mandatory': (True, False),
1252 'is_present': (True, False)})
1253
1254 # Add all _CheckManifest() test cases.
1255 AddParametricTests('CheckManifest',
1256 {'fail_mismatched_block_size': (True, False),
1257 'fail_bad_sigs': (True, False),
1258 'fail_mismatched_oki_ori': (True, False),
1259 'fail_bad_oki': (True, False),
1260 'fail_bad_ori': (True, False),
1261 'fail_bad_nki': (True, False),
1262 'fail_bad_nri': (True, False),
Gilad Arnold382df5c2013-05-03 12:49:28 -07001263 'fail_old_kernel_fs_size': (True, False),
1264 'fail_old_rootfs_fs_size': (True, False),
1265 'fail_new_kernel_fs_size': (True, False),
1266 'fail_new_rootfs_fs_size': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001267
1268 # Add all _CheckOperation() test cases.
1269 AddParametricTests('CheckOperation',
1270 {'op_type_name': ('REPLACE', 'REPLACE_BZ', 'MOVE',
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001271 'BSDIFF', 'SOURCE_COPY',
1272 'SOURCE_BSDIFF'),
Gilad Arnold5502b562013-03-08 13:22:31 -08001273 'is_last': (True, False),
1274 'allow_signature': (True, False),
1275 'allow_unhashed': (True, False),
1276 'fail_src_extents': (True, False),
1277 'fail_dst_extents': (True, False),
1278 'fail_mismatched_data_offset_length': (True, False),
1279 'fail_missing_dst_extents': (True, False),
1280 'fail_src_length': (True, False),
1281 'fail_dst_length': (True, False),
1282 'fail_data_hash': (True, False),
Allie Wood7cf9f132015-02-26 14:28:19 -08001283 'fail_prev_data_offset': (True, False),
1284 'fail_bad_minor_version': (True, False)},
Gilad Arnold5502b562013-03-08 13:22:31 -08001285 validate_func=ValidateCheckOperationTest)
1286
1287 # Add all _CheckOperations() test cases.
1288 AddParametricTests('CheckOperations',
Allie Woodfb04d302015-04-03 14:25:48 -07001289 {'fail_nonexhaustive_full_update': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001290
1291 # Add all _CheckOperations() test cases.
1292 AddParametricTests('CheckSignatures',
1293 {'fail_empty_sigs_blob': (True, False),
1294 'fail_missing_pseudo_op': (True, False),
1295 'fail_mismatched_pseudo_op': (True, False),
1296 'fail_sig_missing_fields': (True, False),
1297 'fail_unknown_sig_version': (True, False),
1298 'fail_incorrect_sig': (True, False)})
1299
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001300 # Add all _CheckManifestMinorVersion() test cases.
1301 AddParametricTests('CheckManifestMinorVersion',
1302 {'minor_version': (None, 0, 1, 2, 555),
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001303 'payload_type': (checker._TYPE_FULL,
1304 checker._TYPE_DELTA)})
1305
Gilad Arnold5502b562013-03-08 13:22:31 -08001306 # Add all Run() test cases.
1307 AddParametricTests('Run',
Gilad Arnold06eea332015-07-13 18:06:33 -07001308 {'rootfs_part_size_provided': (True, False),
1309 'kernel_part_size_provided': (True, False),
1310 'fail_wrong_payload_type': (True, False),
Gilad Arnold5502b562013-03-08 13:22:31 -08001311 'fail_invalid_block_size': (True, False),
1312 'fail_mismatched_block_size': (True, False),
Gilad Arnold06eea332015-07-13 18:06:33 -07001313 'fail_excess_data': (True, False),
1314 'fail_rootfs_part_size_exceeded': (True, False),
1315 'fail_kernel_part_size_exceeded': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001316
1317
1318if __name__ == '__main__':
1319 AddAllParametricTests()
1320 unittest.main()