blob: b761873652590430539f7e782183f651518b2076 [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,
Alex Deymo28466772015-09-11 17:16:44 -070038 'ZERO': common.OpType.ZERO,
39 'DISCARD': common.OpType.DISCARD,
40 'REPLACE_XZ': common.OpType.REPLACE_XZ,
Gilad Arnold5502b562013-03-08 13:22:31 -080041 }
42 return op_name_to_type[op_name]
43
44
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070045def _GetPayloadChecker(payload_gen_write_to_file_func, payload_gen_dargs=None,
46 checker_init_dargs=None):
Gilad Arnold5502b562013-03-08 13:22:31 -080047 """Returns a payload checker from a given payload generator."""
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070048 if payload_gen_dargs is None:
49 payload_gen_dargs = {}
50 if checker_init_dargs is None:
51 checker_init_dargs = {}
52
Gilad Arnold5502b562013-03-08 13:22:31 -080053 payload_file = cStringIO.StringIO()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070054 payload_gen_write_to_file_func(payload_file, **payload_gen_dargs)
Gilad Arnold5502b562013-03-08 13:22:31 -080055 payload_file.seek(0)
56 payload = update_payload.Payload(payload_file)
57 payload.Init()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -070058 return checker.PayloadChecker(payload, **checker_init_dargs)
Gilad Arnold5502b562013-03-08 13:22:31 -080059
60
61def _GetPayloadCheckerWithData(payload_gen):
62 """Returns a payload checker from a given payload generator."""
63 payload_file = cStringIO.StringIO()
64 payload_gen.WriteToFile(payload_file)
65 payload_file.seek(0)
66 payload = update_payload.Payload(payload_file)
67 payload.Init()
68 return checker.PayloadChecker(payload)
69
70
Gilad Arnoldcb638912013-06-24 04:57:11 -070071# This class doesn't need an __init__().
Gilad Arnold5502b562013-03-08 13:22:31 -080072# pylint: disable=W0232
Gilad Arnoldcb638912013-06-24 04:57:11 -070073# Unit testing is all about running protected methods.
Gilad Arnold5502b562013-03-08 13:22:31 -080074# pylint: disable=W0212
Gilad Arnoldcb638912013-06-24 04:57:11 -070075# Don't bark about missing members of classes you cannot import.
Gilad Arnold5502b562013-03-08 13:22:31 -080076# pylint: disable=E1101
77class PayloadCheckerTest(mox.MoxTestBase):
78 """Tests the PayloadChecker class.
79
80 In addition to ordinary testFoo() methods, which are automatically invoked by
81 the unittest framework, in this class we make use of DoBarTest() calls that
82 implement parametric tests of certain features. In order to invoke each test,
83 which embodies a unique combination of parameter values, as a complete unit
84 test, we perform explicit enumeration of the parameter space and create
85 individual invocation contexts for each, which are then bound as
86 testBar__param1=val1__param2=val2(). The enumeration of parameter spaces for
87 all such tests is done in AddAllParametricTests().
Gilad Arnold5502b562013-03-08 13:22:31 -080088 """
89
90 def MockPayload(self):
Allie Woodf5c4f3e2015-02-20 16:57:46 -080091 """Create a mock payload object, complete with a mock manifest."""
Gilad Arnold5502b562013-03-08 13:22:31 -080092 payload = self.mox.CreateMock(update_payload.Payload)
93 payload.is_init = True
94 payload.manifest = self.mox.CreateMock(
95 update_metadata_pb2.DeltaArchiveManifest)
96 return payload
97
98 @staticmethod
99 def NewExtent(start_block, num_blocks):
100 """Returns an Extent message.
101
102 Each of the provided fields is set iff it is >= 0; otherwise, it's left at
103 its default state.
104
105 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700106 start_block: The starting block of the extent.
107 num_blocks: The number of blocks in the extent.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800108
Gilad Arnold5502b562013-03-08 13:22:31 -0800109 Returns:
110 An Extent message.
Gilad Arnold5502b562013-03-08 13:22:31 -0800111 """
112 ex = update_metadata_pb2.Extent()
113 if start_block >= 0:
114 ex.start_block = start_block
115 if num_blocks >= 0:
116 ex.num_blocks = num_blocks
117 return ex
118
119 @staticmethod
120 def NewExtentList(*args):
121 """Returns an list of extents.
122
123 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700124 *args: (start_block, num_blocks) pairs defining the extents.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800125
Gilad Arnold5502b562013-03-08 13:22:31 -0800126 Returns:
127 A list of Extent objects.
Gilad Arnold5502b562013-03-08 13:22:31 -0800128 """
129 ex_list = []
130 for start_block, num_blocks in args:
131 ex_list.append(PayloadCheckerTest.NewExtent(start_block, num_blocks))
132 return ex_list
133
134 @staticmethod
135 def AddToMessage(repeated_field, field_vals):
136 for field_val in field_vals:
137 new_field = repeated_field.add()
138 new_field.CopyFrom(field_val)
139
Gilad Arnold5502b562013-03-08 13:22:31 -0800140 def SetupAddElemTest(self, is_present, is_submsg, convert=str,
141 linebreak=False, indent=0):
142 """Setup for testing of _CheckElem() and its derivatives.
143
144 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700145 is_present: Whether or not the element is found in the message.
146 is_submsg: Whether the element is a sub-message itself.
147 convert: A representation conversion function.
148 linebreak: Whether or not a linebreak is to be used in the report.
149 indent: Indentation used for the report.
Gilad Arnoldf583a7d2015-02-05 13:23:55 -0800150
Gilad Arnold5502b562013-03-08 13:22:31 -0800151 Returns:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700152 msg: A mock message object.
153 report: A mock report object.
154 subreport: A mock sub-report object.
155 name: An element name to check.
156 val: Expected element value.
Gilad Arnold5502b562013-03-08 13:22:31 -0800157 """
158 name = 'foo'
159 val = 'fake submsg' if is_submsg else 'fake field'
160 subreport = 'fake subreport'
161
162 # Create a mock message.
Alex Deymo28466772015-09-11 17:16:44 -0700163 msg = self.mox.CreateMock(update_metadata_pb2._message.Message)
Gilad Arnold5502b562013-03-08 13:22:31 -0800164 msg.HasField(name).AndReturn(is_present)
165 setattr(msg, name, val)
166
167 # Create a mock report.
168 report = self.mox.CreateMock(checker._PayloadReport)
169 if is_present:
170 if is_submsg:
171 report.AddSubReport(name).AndReturn(subreport)
172 else:
173 report.AddField(name, convert(val), linebreak=linebreak, indent=indent)
174
175 self.mox.ReplayAll()
176 return (msg, report, subreport, name, val)
177
178 def DoAddElemTest(self, is_present, is_mandatory, is_submsg, convert,
179 linebreak, indent):
180 """Parametric testing of _CheckElem().
181
182 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700183 is_present: Whether or not the element is found in the message.
184 is_mandatory: Whether or not it's a mandatory element.
185 is_submsg: Whether the element is a sub-message itself.
186 convert: A representation conversion function.
187 linebreak: Whether or not a linebreak is to be used in the report.
188 indent: Indentation used for the report.
Gilad Arnold5502b562013-03-08 13:22:31 -0800189 """
190 msg, report, subreport, name, val = self.SetupAddElemTest(
191 is_present, is_submsg, convert, linebreak, indent)
192
Gilad Arnoldcb638912013-06-24 04:57:11 -0700193 args = (msg, name, report, is_mandatory, is_submsg)
194 kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
Gilad Arnold5502b562013-03-08 13:22:31 -0800195 if is_mandatory and not is_present:
196 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700197 checker.PayloadChecker._CheckElem, *args, **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -0800198 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700199 ret_val, ret_subreport = checker.PayloadChecker._CheckElem(*args,
200 **kwargs)
201 self.assertEquals(val if is_present else None, ret_val)
202 self.assertEquals(subreport if is_present and is_submsg else None,
203 ret_subreport)
Gilad Arnold5502b562013-03-08 13:22:31 -0800204
205 def DoAddFieldTest(self, is_mandatory, is_present, convert, linebreak,
206 indent):
207 """Parametric testing of _Check{Mandatory,Optional}Field().
208
209 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700210 is_mandatory: Whether we're testing a mandatory call.
211 is_present: Whether or not the element is found in the message.
212 convert: A representation conversion function.
213 linebreak: Whether or not a linebreak is to be used in the report.
214 indent: Indentation used for the report.
Gilad Arnold5502b562013-03-08 13:22:31 -0800215 """
216 msg, report, _, name, val = self.SetupAddElemTest(
217 is_present, False, convert, linebreak, indent)
218
219 # Prepare for invocation of the tested method.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700220 args = [msg, name, report]
221 kwargs = {'convert': convert, 'linebreak': linebreak, 'indent': indent}
Gilad Arnold5502b562013-03-08 13:22:31 -0800222 if is_mandatory:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700223 args.append('bar')
Gilad Arnold5502b562013-03-08 13:22:31 -0800224 tested_func = checker.PayloadChecker._CheckMandatoryField
225 else:
226 tested_func = checker.PayloadChecker._CheckOptionalField
227
228 # Test the method call.
229 if is_mandatory and not is_present:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700230 self.assertRaises(update_payload.PayloadError, tested_func, *args,
231 **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -0800232 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700233 ret_val = tested_func(*args, **kwargs)
234 self.assertEquals(val if is_present else None, ret_val)
Gilad Arnold5502b562013-03-08 13:22:31 -0800235
236 def DoAddSubMsgTest(self, is_mandatory, is_present):
237 """Parametrized testing of _Check{Mandatory,Optional}SubMsg().
238
239 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700240 is_mandatory: Whether we're testing a mandatory call.
241 is_present: Whether or not the element is found in the message.
Gilad Arnold5502b562013-03-08 13:22:31 -0800242 """
243 msg, report, subreport, name, val = self.SetupAddElemTest(is_present, True)
244
245 # Prepare for invocation of the tested method.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700246 args = [msg, name, report]
Gilad Arnold5502b562013-03-08 13:22:31 -0800247 if is_mandatory:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700248 args.append('bar')
Gilad Arnold5502b562013-03-08 13:22:31 -0800249 tested_func = checker.PayloadChecker._CheckMandatorySubMsg
250 else:
251 tested_func = checker.PayloadChecker._CheckOptionalSubMsg
252
253 # Test the method call.
254 if is_mandatory and not is_present:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700255 self.assertRaises(update_payload.PayloadError, tested_func, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800256 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700257 ret_val, ret_subreport = tested_func(*args)
258 self.assertEquals(val if is_present else None, ret_val)
259 self.assertEquals(subreport if is_present else None, ret_subreport)
Gilad Arnold5502b562013-03-08 13:22:31 -0800260
261 def testCheckPresentIff(self):
262 """Tests _CheckPresentIff()."""
263 self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
264 None, None, 'foo', 'bar', 'baz'))
265 self.assertIsNone(checker.PayloadChecker._CheckPresentIff(
266 'a', 'b', 'foo', 'bar', 'baz'))
267 self.assertRaises(update_payload.PayloadError,
268 checker.PayloadChecker._CheckPresentIff,
269 'a', None, 'foo', 'bar', 'baz')
270 self.assertRaises(update_payload.PayloadError,
271 checker.PayloadChecker._CheckPresentIff,
272 None, 'b', 'foo', 'bar', 'baz')
273
274 def DoCheckSha256SignatureTest(self, expect_pass, expect_subprocess_call,
275 sig_data, sig_asn1_header,
276 returned_signed_hash, expected_signed_hash):
277 """Parametric testing of _CheckSha256SignatureTest().
278
279 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700280 expect_pass: Whether or not it should pass.
281 expect_subprocess_call: Whether to expect the openssl call to happen.
282 sig_data: The signature raw data.
283 sig_asn1_header: The ASN1 header.
284 returned_signed_hash: The signed hash data retuned by openssl.
285 expected_signed_hash: The signed hash data to compare against.
Gilad Arnold5502b562013-03-08 13:22:31 -0800286 """
Gilad Arnoldcb638912013-06-24 04:57:11 -0700287 try:
288 # Stub out the subprocess invocation.
289 self.mox.StubOutWithMock(checker.PayloadChecker, '_Run')
290 if expect_subprocess_call:
291 checker.PayloadChecker._Run(
292 mox.IsA(list), send_data=sig_data).AndReturn(
293 (sig_asn1_header + returned_signed_hash, None))
Gilad Arnold5502b562013-03-08 13:22:31 -0800294
Gilad Arnoldcb638912013-06-24 04:57:11 -0700295 self.mox.ReplayAll()
296 if expect_pass:
297 self.assertIsNone(checker.PayloadChecker._CheckSha256Signature(
298 sig_data, 'foo', expected_signed_hash, 'bar'))
299 else:
300 self.assertRaises(update_payload.PayloadError,
301 checker.PayloadChecker._CheckSha256Signature,
302 sig_data, 'foo', expected_signed_hash, 'bar')
303 finally:
304 self.mox.UnsetStubs()
Gilad Arnold5502b562013-03-08 13:22:31 -0800305
306 def testCheckSha256Signature_Pass(self):
307 """Tests _CheckSha256Signature(); pass case."""
308 sig_data = 'fake-signature'.ljust(256)
309 signed_hash = hashlib.sha256('fake-data').digest()
310 self.DoCheckSha256SignatureTest(True, True, sig_data,
311 common.SIG_ASN1_HEADER, signed_hash,
312 signed_hash)
313
314 def testCheckSha256Signature_FailBadSignature(self):
315 """Tests _CheckSha256Signature(); fails due to malformed signature."""
Gilad Arnoldcb638912013-06-24 04:57:11 -0700316 sig_data = 'fake-signature' # Malformed (not 256 bytes in length).
Gilad Arnold5502b562013-03-08 13:22:31 -0800317 signed_hash = hashlib.sha256('fake-data').digest()
318 self.DoCheckSha256SignatureTest(False, False, sig_data,
319 common.SIG_ASN1_HEADER, signed_hash,
320 signed_hash)
321
322 def testCheckSha256Signature_FailBadOutputLength(self):
323 """Tests _CheckSha256Signature(); fails due to unexpected output length."""
324 sig_data = 'fake-signature'.ljust(256)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700325 signed_hash = 'fake-hash' # Malformed (not 32 bytes in length).
Gilad Arnold5502b562013-03-08 13:22:31 -0800326 self.DoCheckSha256SignatureTest(False, True, sig_data,
327 common.SIG_ASN1_HEADER, signed_hash,
328 signed_hash)
329
330 def testCheckSha256Signature_FailBadAsnHeader(self):
331 """Tests _CheckSha256Signature(); fails due to bad ASN1 header."""
332 sig_data = 'fake-signature'.ljust(256)
333 signed_hash = hashlib.sha256('fake-data').digest()
334 bad_asn1_header = 'bad-asn-header'.ljust(len(common.SIG_ASN1_HEADER))
335 self.DoCheckSha256SignatureTest(False, True, sig_data, bad_asn1_header,
336 signed_hash, signed_hash)
337
338 def testCheckSha256Signature_FailBadHash(self):
339 """Tests _CheckSha256Signature(); fails due to bad hash returned."""
340 sig_data = 'fake-signature'.ljust(256)
341 expected_signed_hash = hashlib.sha256('fake-data').digest()
342 returned_signed_hash = hashlib.sha256('bad-fake-data').digest()
343 self.DoCheckSha256SignatureTest(False, True, sig_data,
344 common.SIG_ASN1_HEADER,
345 expected_signed_hash, returned_signed_hash)
346
347 def testCheckBlocksFitLength_Pass(self):
348 """Tests _CheckBlocksFitLength(); pass case."""
349 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
350 64, 4, 16, 'foo'))
351 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
352 60, 4, 16, 'foo'))
353 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
354 49, 4, 16, 'foo'))
355 self.assertIsNone(checker.PayloadChecker._CheckBlocksFitLength(
356 48, 3, 16, 'foo'))
357
358 def testCheckBlocksFitLength_TooManyBlocks(self):
359 """Tests _CheckBlocksFitLength(); fails due to excess blocks."""
360 self.assertRaises(update_payload.PayloadError,
361 checker.PayloadChecker._CheckBlocksFitLength,
362 64, 5, 16, 'foo')
363 self.assertRaises(update_payload.PayloadError,
364 checker.PayloadChecker._CheckBlocksFitLength,
365 60, 5, 16, 'foo')
366 self.assertRaises(update_payload.PayloadError,
367 checker.PayloadChecker._CheckBlocksFitLength,
368 49, 5, 16, 'foo')
369 self.assertRaises(update_payload.PayloadError,
370 checker.PayloadChecker._CheckBlocksFitLength,
371 48, 4, 16, 'foo')
372
373 def testCheckBlocksFitLength_TooFewBlocks(self):
374 """Tests _CheckBlocksFitLength(); fails due to insufficient blocks."""
375 self.assertRaises(update_payload.PayloadError,
376 checker.PayloadChecker._CheckBlocksFitLength,
377 64, 3, 16, 'foo')
378 self.assertRaises(update_payload.PayloadError,
379 checker.PayloadChecker._CheckBlocksFitLength,
380 60, 3, 16, 'foo')
381 self.assertRaises(update_payload.PayloadError,
382 checker.PayloadChecker._CheckBlocksFitLength,
383 49, 3, 16, 'foo')
384 self.assertRaises(update_payload.PayloadError,
385 checker.PayloadChecker._CheckBlocksFitLength,
386 48, 2, 16, 'foo')
387
388 def DoCheckManifestTest(self, fail_mismatched_block_size, fail_bad_sigs,
389 fail_mismatched_oki_ori, fail_bad_oki, fail_bad_ori,
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800390 fail_bad_nki, fail_bad_nri, fail_old_kernel_fs_size,
391 fail_old_rootfs_fs_size, fail_new_kernel_fs_size,
392 fail_new_rootfs_fs_size):
Gilad Arnold5502b562013-03-08 13:22:31 -0800393 """Parametric testing of _CheckManifest().
394
395 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700396 fail_mismatched_block_size: Simulate a missing block_size field.
397 fail_bad_sigs: Make signatures descriptor inconsistent.
398 fail_mismatched_oki_ori: Make old rootfs/kernel info partially present.
399 fail_bad_oki: Tamper with old kernel info.
400 fail_bad_ori: Tamper with old rootfs info.
401 fail_bad_nki: Tamper with new kernel info.
402 fail_bad_nri: Tamper with new rootfs info.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700403 fail_old_kernel_fs_size: Make old kernel fs size too big.
404 fail_old_rootfs_fs_size: Make old rootfs fs size too big.
405 fail_new_kernel_fs_size: Make new kernel fs size too big.
406 fail_new_rootfs_fs_size: Make new rootfs fs size too big.
Gilad Arnold5502b562013-03-08 13:22:31 -0800407 """
408 # Generate a test payload. For this test, we only care about the manifest
409 # and don't need any data blobs, hence we can use a plain paylaod generator
410 # (which also gives us more control on things that can be screwed up).
411 payload_gen = test_utils.PayloadGenerator()
412
413 # Tamper with block size, if required.
414 if fail_mismatched_block_size:
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700415 payload_gen.SetBlockSize(test_utils.KiB(1))
Gilad Arnold5502b562013-03-08 13:22:31 -0800416 else:
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700417 payload_gen.SetBlockSize(test_utils.KiB(4))
Gilad Arnold5502b562013-03-08 13:22:31 -0800418
419 # Add some operations.
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800420 payload_gen.AddOperation(False, common.OpType.MOVE,
421 src_extents=[(0, 16), (16, 497)],
422 dst_extents=[(16, 496), (0, 16)])
423 payload_gen.AddOperation(True, common.OpType.MOVE,
424 src_extents=[(0, 8), (8, 8)],
425 dst_extents=[(8, 8), (0, 8)])
Gilad Arnold5502b562013-03-08 13:22:31 -0800426
427 # Set an invalid signatures block (offset but no size), if required.
428 if fail_bad_sigs:
429 payload_gen.SetSignatures(32, None)
430
Gilad Arnold382df5c2013-05-03 12:49:28 -0700431 # Set partition / filesystem sizes.
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700432 rootfs_part_size = test_utils.MiB(8)
433 kernel_part_size = test_utils.KiB(512)
Gilad Arnold382df5c2013-05-03 12:49:28 -0700434 old_rootfs_fs_size = new_rootfs_fs_size = rootfs_part_size
435 old_kernel_fs_size = new_kernel_fs_size = kernel_part_size
436 if fail_old_kernel_fs_size:
437 old_kernel_fs_size += 100
438 if fail_old_rootfs_fs_size:
439 old_rootfs_fs_size += 100
440 if fail_new_kernel_fs_size:
441 new_kernel_fs_size += 100
442 if fail_new_rootfs_fs_size:
443 new_rootfs_fs_size += 100
444
Gilad Arnold5502b562013-03-08 13:22:31 -0800445 # Add old kernel/rootfs partition info, as required.
Gilad Arnold382df5c2013-05-03 12:49:28 -0700446 if fail_mismatched_oki_ori or fail_old_kernel_fs_size or fail_bad_oki:
Gilad Arnold5502b562013-03-08 13:22:31 -0800447 oki_hash = (None if fail_bad_oki
448 else hashlib.sha256('fake-oki-content').digest())
Gilad Arnold382df5c2013-05-03 12:49:28 -0700449 payload_gen.SetPartInfo(True, False, old_kernel_fs_size, oki_hash)
450 if not fail_mismatched_oki_ori and (fail_old_rootfs_fs_size or
451 fail_bad_ori):
452 ori_hash = (None if fail_bad_ori
453 else hashlib.sha256('fake-ori-content').digest())
454 payload_gen.SetPartInfo(False, False, old_rootfs_fs_size, ori_hash)
Gilad Arnold5502b562013-03-08 13:22:31 -0800455
456 # Add new kernel/rootfs partition info.
457 payload_gen.SetPartInfo(
Gilad Arnold382df5c2013-05-03 12:49:28 -0700458 True, True, new_kernel_fs_size,
Gilad Arnold5502b562013-03-08 13:22:31 -0800459 None if fail_bad_nki else hashlib.sha256('fake-nki-content').digest())
460 payload_gen.SetPartInfo(
Gilad Arnold382df5c2013-05-03 12:49:28 -0700461 False, True, new_rootfs_fs_size,
Gilad Arnold5502b562013-03-08 13:22:31 -0800462 None if fail_bad_nri else hashlib.sha256('fake-nri-content').digest())
463
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700464 # Set the minor version.
465 payload_gen.SetMinorVersion(0)
466
Gilad Arnold5502b562013-03-08 13:22:31 -0800467 # Create the test object.
468 payload_checker = _GetPayloadChecker(payload_gen.WriteToFile)
469 report = checker._PayloadReport()
470
471 should_fail = (fail_mismatched_block_size or fail_bad_sigs or
472 fail_mismatched_oki_ori or fail_bad_oki or fail_bad_ori or
Gilad Arnold5bc7fbe2015-02-05 13:01:09 -0800473 fail_bad_nki or fail_bad_nri or fail_old_kernel_fs_size or
474 fail_old_rootfs_fs_size or fail_new_kernel_fs_size or
475 fail_new_rootfs_fs_size)
Gilad Arnold5502b562013-03-08 13:22:31 -0800476 if should_fail:
477 self.assertRaises(update_payload.PayloadError,
Gilad Arnold382df5c2013-05-03 12:49:28 -0700478 payload_checker._CheckManifest, report,
479 rootfs_part_size, kernel_part_size)
Gilad Arnold5502b562013-03-08 13:22:31 -0800480 else:
Gilad Arnold382df5c2013-05-03 12:49:28 -0700481 self.assertIsNone(payload_checker._CheckManifest(report,
482 rootfs_part_size,
483 kernel_part_size))
Gilad Arnold5502b562013-03-08 13:22:31 -0800484
485 def testCheckLength(self):
486 """Tests _CheckLength()."""
487 payload_checker = checker.PayloadChecker(self.MockPayload())
488 block_size = payload_checker.block_size
489
490 # Passes.
491 self.assertIsNone(payload_checker._CheckLength(
492 int(3.5 * block_size), 4, 'foo', 'bar'))
493 # Fails, too few blocks.
494 self.assertRaises(update_payload.PayloadError,
495 payload_checker._CheckLength,
496 int(3.5 * block_size), 3, 'foo', 'bar')
497 # Fails, too many blocks.
498 self.assertRaises(update_payload.PayloadError,
499 payload_checker._CheckLength,
500 int(3.5 * block_size), 5, 'foo', 'bar')
501
502 def testCheckExtents(self):
503 """Tests _CheckExtents()."""
504 payload_checker = checker.PayloadChecker(self.MockPayload())
505 block_size = payload_checker.block_size
506
507 # Passes w/ all real extents.
508 extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
509 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700510 23,
Gilad Arnold5502b562013-03-08 13:22:31 -0800511 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700512 collections.defaultdict(int), 'foo'))
Gilad Arnold5502b562013-03-08 13:22:31 -0800513
514 # Passes w/ pseudo-extents (aka sparse holes).
515 extents = self.NewExtentList((0, 4), (common.PSEUDO_EXTENT_MARKER, 5),
516 (8, 3))
517 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700518 12,
Gilad Arnold5502b562013-03-08 13:22:31 -0800519 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
520 collections.defaultdict(int), 'foo',
Gilad Arnoldcb638912013-06-24 04:57:11 -0700521 allow_pseudo=True))
Gilad Arnold5502b562013-03-08 13:22:31 -0800522
523 # Passes w/ pseudo-extent due to a signature.
524 extents = self.NewExtentList((common.PSEUDO_EXTENT_MARKER, 2))
525 self.assertEquals(
Gilad Arnoldcb638912013-06-24 04:57:11 -0700526 2,
Gilad Arnold5502b562013-03-08 13:22:31 -0800527 payload_checker._CheckExtents(extents, (1024 + 16) * block_size,
528 collections.defaultdict(int), 'foo',
Gilad Arnoldcb638912013-06-24 04:57:11 -0700529 allow_signature=True))
Gilad Arnold5502b562013-03-08 13:22:31 -0800530
531 # Fails, extent missing a start block.
532 extents = self.NewExtentList((-1, 4), (8, 3), (1024, 16))
533 self.assertRaises(
534 update_payload.PayloadError, payload_checker._CheckExtents,
535 extents, (1024 + 16) * block_size, collections.defaultdict(int),
536 'foo')
537
538 # Fails, extent missing block count.
539 extents = self.NewExtentList((0, -1), (8, 3), (1024, 16))
540 self.assertRaises(
541 update_payload.PayloadError, payload_checker._CheckExtents,
542 extents, (1024 + 16) * block_size, collections.defaultdict(int),
543 'foo')
544
545 # Fails, extent has zero blocks.
546 extents = self.NewExtentList((0, 4), (8, 3), (1024, 0))
547 self.assertRaises(
548 update_payload.PayloadError, payload_checker._CheckExtents,
549 extents, (1024 + 16) * block_size, collections.defaultdict(int),
550 'foo')
551
552 # Fails, extent exceeds partition boundaries.
553 extents = self.NewExtentList((0, 4), (8, 3), (1024, 16))
554 self.assertRaises(
555 update_payload.PayloadError, payload_checker._CheckExtents,
556 extents, (1024 + 15) * block_size, collections.defaultdict(int),
557 'foo')
558
559 def testCheckReplaceOperation(self):
560 """Tests _CheckReplaceOperation() where op.type == REPLACE."""
561 payload_checker = checker.PayloadChecker(self.MockPayload())
562 block_size = payload_checker.block_size
563 data_length = 10000
564
565 op = self.mox.CreateMock(
Alex Deymo28466772015-09-11 17:16:44 -0700566 update_metadata_pb2.InstallOperation)
Gilad Arnold5502b562013-03-08 13:22:31 -0800567 op.type = common.OpType.REPLACE
568
569 # Pass.
570 op.src_extents = []
571 self.assertIsNone(
572 payload_checker._CheckReplaceOperation(
573 op, data_length, (data_length + block_size - 1) / block_size,
574 'foo'))
575
576 # Fail, src extents founds.
577 op.src_extents = ['bar']
578 self.assertRaises(
579 update_payload.PayloadError,
580 payload_checker._CheckReplaceOperation,
581 op, data_length, (data_length + block_size - 1) / block_size, 'foo')
582
583 # Fail, missing data.
584 op.src_extents = []
585 self.assertRaises(
586 update_payload.PayloadError,
587 payload_checker._CheckReplaceOperation,
588 op, None, (data_length + block_size - 1) / block_size, 'foo')
589
590 # Fail, length / block number mismatch.
591 op.src_extents = ['bar']
592 self.assertRaises(
593 update_payload.PayloadError,
594 payload_checker._CheckReplaceOperation,
595 op, data_length, (data_length + block_size - 1) / block_size + 1, 'foo')
596
597 def testCheckReplaceBzOperation(self):
598 """Tests _CheckReplaceOperation() where op.type == REPLACE_BZ."""
599 payload_checker = checker.PayloadChecker(self.MockPayload())
600 block_size = payload_checker.block_size
601 data_length = block_size * 3
602
603 op = self.mox.CreateMock(
Alex Deymo28466772015-09-11 17:16:44 -0700604 update_metadata_pb2.InstallOperation)
Gilad Arnold5502b562013-03-08 13:22:31 -0800605 op.type = common.OpType.REPLACE_BZ
606
607 # Pass.
608 op.src_extents = []
609 self.assertIsNone(
610 payload_checker._CheckReplaceOperation(
611 op, data_length, (data_length + block_size - 1) / block_size + 5,
612 'foo'))
613
614 # Fail, src extents founds.
615 op.src_extents = ['bar']
616 self.assertRaises(
617 update_payload.PayloadError,
618 payload_checker._CheckReplaceOperation,
619 op, data_length, (data_length + block_size - 1) / block_size + 5, 'foo')
620
621 # Fail, missing data.
622 op.src_extents = []
623 self.assertRaises(
624 update_payload.PayloadError,
625 payload_checker._CheckReplaceOperation,
626 op, None, (data_length + block_size - 1) / block_size, 'foo')
627
628 # Fail, too few blocks to justify BZ.
629 op.src_extents = []
630 self.assertRaises(
631 update_payload.PayloadError,
632 payload_checker._CheckReplaceOperation,
633 op, data_length, (data_length + block_size - 1) / block_size, 'foo')
634
635 def testCheckMoveOperation_Pass(self):
636 """Tests _CheckMoveOperation(); pass case."""
637 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700638 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800639 op.type = common.OpType.MOVE
640
641 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700642 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800643 self.AddToMessage(op.dst_extents,
644 self.NewExtentList((16, 128), (512, 6)))
645 self.assertIsNone(
646 payload_checker._CheckMoveOperation(op, None, 134, 134, 'foo'))
647
648 def testCheckMoveOperation_FailContainsData(self):
649 """Tests _CheckMoveOperation(); fails, message contains data."""
650 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700651 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800652 op.type = common.OpType.MOVE
653
654 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700655 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800656 self.AddToMessage(op.dst_extents,
657 self.NewExtentList((16, 128), (512, 6)))
658 self.assertRaises(
659 update_payload.PayloadError,
660 payload_checker._CheckMoveOperation,
661 op, 1024, 134, 134, 'foo')
662
663 def testCheckMoveOperation_FailInsufficientSrcBlocks(self):
664 """Tests _CheckMoveOperation(); fails, not enough actual src blocks."""
665 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700666 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800667 op.type = common.OpType.MOVE
668
669 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700670 self.NewExtentList((1, 4), (12, 2), (1024, 127)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800671 self.AddToMessage(op.dst_extents,
672 self.NewExtentList((16, 128), (512, 6)))
673 self.assertRaises(
674 update_payload.PayloadError,
675 payload_checker._CheckMoveOperation,
676 op, None, 134, 134, 'foo')
677
678 def testCheckMoveOperation_FailInsufficientDstBlocks(self):
679 """Tests _CheckMoveOperation(); fails, not enough actual dst blocks."""
680 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700681 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800682 op.type = common.OpType.MOVE
683
684 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700685 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800686 self.AddToMessage(op.dst_extents,
687 self.NewExtentList((16, 128), (512, 5)))
688 self.assertRaises(
689 update_payload.PayloadError,
690 payload_checker._CheckMoveOperation,
691 op, None, 134, 134, 'foo')
692
693 def testCheckMoveOperation_FailExcessSrcBlocks(self):
694 """Tests _CheckMoveOperation(); fails, too many actual src blocks."""
695 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700696 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800697 op.type = common.OpType.MOVE
698
699 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700700 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800701 self.AddToMessage(op.dst_extents,
702 self.NewExtentList((16, 128), (512, 5)))
703 self.assertRaises(
704 update_payload.PayloadError,
705 payload_checker._CheckMoveOperation,
706 op, None, 134, 134, 'foo')
707 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700708 self.NewExtentList((1, 4), (12, 2), (1024, 129)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800709 self.AddToMessage(op.dst_extents,
710 self.NewExtentList((16, 128), (512, 6)))
711 self.assertRaises(
712 update_payload.PayloadError,
713 payload_checker._CheckMoveOperation,
714 op, None, 134, 134, 'foo')
715
716 def testCheckMoveOperation_FailExcessDstBlocks(self):
717 """Tests _CheckMoveOperation(); fails, too many actual dst blocks."""
718 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700719 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800720 op.type = common.OpType.MOVE
721
722 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700723 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800724 self.AddToMessage(op.dst_extents,
725 self.NewExtentList((16, 128), (512, 7)))
726 self.assertRaises(
727 update_payload.PayloadError,
728 payload_checker._CheckMoveOperation,
729 op, None, 134, 134, 'foo')
730
731 def testCheckMoveOperation_FailStagnantBlocks(self):
732 """Tests _CheckMoveOperation(); fails, there are blocks that do not move."""
733 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700734 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800735 op.type = common.OpType.MOVE
736
737 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700738 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
739 self.AddToMessage(op.dst_extents,
740 self.NewExtentList((8, 128), (512, 6)))
741 self.assertRaises(
742 update_payload.PayloadError,
743 payload_checker._CheckMoveOperation,
744 op, None, 134, 134, 'foo')
745
746 def testCheckMoveOperation_FailZeroStartBlock(self):
747 """Tests _CheckMoveOperation(); fails, has extent with start block 0."""
748 payload_checker = checker.PayloadChecker(self.MockPayload())
Alex Deymo28466772015-09-11 17:16:44 -0700749 op = update_metadata_pb2.InstallOperation()
Allie Woodb065e132015-04-24 10:20:27 -0700750 op.type = common.OpType.MOVE
751
752 self.AddToMessage(op.src_extents,
Gilad Arnold5502b562013-03-08 13:22:31 -0800753 self.NewExtentList((0, 4), (12, 2), (1024, 128)))
754 self.AddToMessage(op.dst_extents,
755 self.NewExtentList((8, 128), (512, 6)))
756 self.assertRaises(
757 update_payload.PayloadError,
758 payload_checker._CheckMoveOperation,
759 op, None, 134, 134, 'foo')
760
Allie Woodb065e132015-04-24 10:20:27 -0700761 self.AddToMessage(op.src_extents,
762 self.NewExtentList((1, 4), (12, 2), (1024, 128)))
763 self.AddToMessage(op.dst_extents,
764 self.NewExtentList((0, 128), (512, 6)))
765 self.assertRaises(
766 update_payload.PayloadError,
767 payload_checker._CheckMoveOperation,
768 op, None, 134, 134, 'foo')
769
Gilad Arnold5502b562013-03-08 13:22:31 -0800770 def testCheckBsdiff(self):
771 """Tests _CheckMoveOperation()."""
772 payload_checker = checker.PayloadChecker(self.MockPayload())
773
774 # Pass.
775 self.assertIsNone(
776 payload_checker._CheckBsdiffOperation(10000, 3, 'foo'))
777
778 # Fail, missing data blob.
779 self.assertRaises(
780 update_payload.PayloadError,
781 payload_checker._CheckBsdiffOperation,
782 None, 3, 'foo')
783
784 # Fail, too big of a diff blob (unjustified).
785 self.assertRaises(
786 update_payload.PayloadError,
787 payload_checker._CheckBsdiffOperation,
788 10000, 2, 'foo')
789
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800790 def testCheckSourceCopyOperation_Pass(self):
791 """Tests _CheckSourceCopyOperation(); pass case."""
792 payload_checker = checker.PayloadChecker(self.MockPayload())
793 self.assertIsNone(
794 payload_checker._CheckSourceCopyOperation(None, 134, 134, 'foo'))
795
796 def testCheckSourceCopyOperation_FailContainsData(self):
797 """Tests _CheckSourceCopyOperation(); message contains data."""
798 payload_checker = checker.PayloadChecker(self.MockPayload())
799 self.assertRaises(update_payload.PayloadError,
800 payload_checker._CheckSourceCopyOperation,
801 134, 0, 0, 'foo')
802
803 def testCheckSourceCopyOperation_FailBlockCountsMismatch(self):
804 """Tests _CheckSourceCopyOperation(); src and dst block totals not equal."""
805 payload_checker = checker.PayloadChecker(self.MockPayload())
806 self.assertRaises(update_payload.PayloadError,
807 payload_checker._CheckSourceCopyOperation,
808 None, 0, 1, 'foo')
809
Gilad Arnold5502b562013-03-08 13:22:31 -0800810 def DoCheckOperationTest(self, op_type_name, is_last, allow_signature,
811 allow_unhashed, fail_src_extents, fail_dst_extents,
812 fail_mismatched_data_offset_length,
813 fail_missing_dst_extents, fail_src_length,
814 fail_dst_length, fail_data_hash,
Allie Wood7cf9f132015-02-26 14:28:19 -0800815 fail_prev_data_offset, fail_bad_minor_version):
Gilad Arnold5502b562013-03-08 13:22:31 -0800816 """Parametric testing of _CheckOperation().
817
818 Args:
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800819 op_type_name: 'REPLACE', 'REPLACE_BZ', 'MOVE', 'BSDIFF', 'SOURCE_COPY',
820 or 'SOURCE_BSDIFF'.
Gilad Arnoldcb638912013-06-24 04:57:11 -0700821 is_last: Whether we're testing the last operation in a sequence.
822 allow_signature: Whether we're testing a signature-capable operation.
823 allow_unhashed: Whether we're allowing to not hash the data.
824 fail_src_extents: Tamper with src extents.
825 fail_dst_extents: Tamper with dst extents.
826 fail_mismatched_data_offset_length: Make data_{offset,length}
827 inconsistent.
828 fail_missing_dst_extents: Do not include dst extents.
829 fail_src_length: Make src length inconsistent.
830 fail_dst_length: Make dst length inconsistent.
831 fail_data_hash: Tamper with the data blob hash.
832 fail_prev_data_offset: Make data space uses incontiguous.
Allie Wood7cf9f132015-02-26 14:28:19 -0800833 fail_bad_minor_version: Make minor version incompatible with op.
Gilad Arnold5502b562013-03-08 13:22:31 -0800834 """
835 op_type = _OpTypeByName(op_type_name)
836
837 # Create the test object.
838 payload = self.MockPayload()
Gilad Arnoldeaed0d12013-04-30 15:38:22 -0700839 payload_checker = checker.PayloadChecker(payload,
840 allow_unhashed=allow_unhashed)
Gilad Arnold5502b562013-03-08 13:22:31 -0800841 block_size = payload_checker.block_size
842
843 # Create auxiliary arguments.
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700844 old_part_size = test_utils.MiB(4)
845 new_part_size = test_utils.MiB(8)
Gilad Arnold5502b562013-03-08 13:22:31 -0800846 old_block_counters = array.array(
847 'B', [0] * ((old_part_size + block_size - 1) / block_size))
848 new_block_counters = array.array(
849 'B', [0] * ((new_part_size + block_size - 1) / block_size))
850 prev_data_offset = 1876
851 blob_hash_counts = collections.defaultdict(int)
852
853 # Create the operation object for the test.
Alex Deymo28466772015-09-11 17:16:44 -0700854 op = update_metadata_pb2.InstallOperation()
Gilad Arnold5502b562013-03-08 13:22:31 -0800855 op.type = op_type
856
857 total_src_blocks = 0
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800858 if op_type in (common.OpType.MOVE, common.OpType.BSDIFF,
859 common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
Gilad Arnold5502b562013-03-08 13:22:31 -0800860 if fail_src_extents:
861 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700862 self.NewExtentList((1, 0)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800863 else:
864 self.AddToMessage(op.src_extents,
Allie Woodb065e132015-04-24 10:20:27 -0700865 self.NewExtentList((1, 16)))
Gilad Arnold5502b562013-03-08 13:22:31 -0800866 total_src_blocks = 16
867
Allie Wood7cf9f132015-02-26 14:28:19 -0800868 if op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700869 payload_checker.minor_version = 0
Allie Wood7cf9f132015-02-26 14:28:19 -0800870 elif op_type in (common.OpType.MOVE, common.OpType.BSDIFF):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700871 payload_checker.minor_version = 2 if fail_bad_minor_version else 1
Allie Wood7cf9f132015-02-26 14:28:19 -0800872 elif op_type in (common.OpType.SOURCE_COPY, common.OpType.SOURCE_BSDIFF):
Gilad Arnold0d575cd2015-07-13 17:29:21 -0700873 payload_checker.minor_version = 1 if fail_bad_minor_version else 2
Allie Wood7cf9f132015-02-26 14:28:19 -0800874
Allie Woodf5c4f3e2015-02-20 16:57:46 -0800875 if op_type not in (common.OpType.MOVE, common.OpType.SOURCE_COPY):
Gilad Arnold5502b562013-03-08 13:22:31 -0800876 if not fail_mismatched_data_offset_length:
877 op.data_length = 16 * block_size - 8
878 if fail_prev_data_offset:
879 op.data_offset = prev_data_offset + 16
880 else:
881 op.data_offset = prev_data_offset
882
883 fake_data = 'fake-data'.ljust(op.data_length)
884 if not (allow_unhashed or (is_last and allow_signature and
885 op_type == common.OpType.REPLACE)):
886 if not fail_data_hash:
887 # Create a valid data blob hash.
888 op.data_sha256_hash = hashlib.sha256(fake_data).digest()
889 payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
890 fake_data)
891 elif fail_data_hash:
892 # Create an invalid data blob hash.
893 op.data_sha256_hash = hashlib.sha256(
894 fake_data.replace(' ', '-')).digest()
895 payload.ReadDataBlob(op.data_offset, op.data_length).AndReturn(
896 fake_data)
897
898 total_dst_blocks = 0
899 if not fail_missing_dst_extents:
900 total_dst_blocks = 16
901 if fail_dst_extents:
902 self.AddToMessage(op.dst_extents,
903 self.NewExtentList((4, 16), (32, 0)))
904 else:
905 self.AddToMessage(op.dst_extents,
906 self.NewExtentList((4, 8), (64, 8)))
907
908 if total_src_blocks:
909 if fail_src_length:
910 op.src_length = total_src_blocks * block_size + 8
911 else:
912 op.src_length = total_src_blocks * block_size
913 elif fail_src_length:
914 # Add an orphaned src_length.
915 op.src_length = 16
916
917 if total_dst_blocks:
918 if fail_dst_length:
919 op.dst_length = total_dst_blocks * block_size + 8
920 else:
921 op.dst_length = total_dst_blocks * block_size
922
923 self.mox.ReplayAll()
924 should_fail = (fail_src_extents or fail_dst_extents or
925 fail_mismatched_data_offset_length or
926 fail_missing_dst_extents or fail_src_length or
Allie Wood7cf9f132015-02-26 14:28:19 -0800927 fail_dst_length or fail_data_hash or fail_prev_data_offset or
928 fail_bad_minor_version)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700929 args = (op, 'foo', is_last, old_block_counters, new_block_counters,
930 old_part_size, new_part_size, prev_data_offset, allow_signature,
931 blob_hash_counts)
Gilad Arnold5502b562013-03-08 13:22:31 -0800932 if should_fail:
933 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700934 payload_checker._CheckOperation, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800935 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700936 self.assertEqual(op.data_length if op.HasField('data_length') else 0,
937 payload_checker._CheckOperation(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -0800938
939 def testAllocBlockCounters(self):
940 """Tests _CheckMoveOperation()."""
941 payload_checker = checker.PayloadChecker(self.MockPayload())
942 block_size = payload_checker.block_size
943
944 # Check allocation for block-aligned partition size, ensure it's integers.
945 result = payload_checker._AllocBlockCounters(16 * block_size)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700946 self.assertEqual(16, len(result))
947 self.assertEqual(int, type(result[0]))
Gilad Arnold5502b562013-03-08 13:22:31 -0800948
949 # Check allocation of unaligned partition sizes.
950 result = payload_checker._AllocBlockCounters(16 * block_size - 1)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700951 self.assertEqual(16, len(result))
Gilad Arnold5502b562013-03-08 13:22:31 -0800952 result = payload_checker._AllocBlockCounters(16 * block_size + 1)
Gilad Arnoldcb638912013-06-24 04:57:11 -0700953 self.assertEqual(17, len(result))
Gilad Arnold5502b562013-03-08 13:22:31 -0800954
Allie Woodfb04d302015-04-03 14:25:48 -0700955 def DoCheckOperationsTest(self, fail_nonexhaustive_full_update):
Gilad Arnold5502b562013-03-08 13:22:31 -0800956 # Generate a test payload. For this test, we only care about one
957 # (arbitrary) set of operations, so we'll only be generating kernel and
958 # test with them.
959 payload_gen = test_utils.PayloadGenerator()
960
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700961 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -0800962 payload_gen.SetBlockSize(block_size)
963
Gilad Arnold18f4f9f2013-04-02 16:24:41 -0700964 rootfs_part_size = test_utils.MiB(8)
Gilad Arnold5502b562013-03-08 13:22:31 -0800965
966 # Fake rootfs operations in a full update, tampered with as required.
967 rootfs_op_type = common.OpType.REPLACE
Gilad Arnold5502b562013-03-08 13:22:31 -0800968 rootfs_data_length = rootfs_part_size
969 if fail_nonexhaustive_full_update:
970 rootfs_data_length -= block_size
971
972 payload_gen.AddOperation(False, rootfs_op_type,
973 dst_extents=[(0, rootfs_data_length / block_size)],
974 data_offset=0,
975 data_length=rootfs_data_length)
976
977 # Create the test object.
Gilad Arnoldeaed0d12013-04-30 15:38:22 -0700978 payload_checker = _GetPayloadChecker(payload_gen.WriteToFile,
979 checker_init_dargs={
980 'allow_unhashed': True})
Gilad Arnold5502b562013-03-08 13:22:31 -0800981 payload_checker.payload_type = checker._TYPE_FULL
982 report = checker._PayloadReport()
983
Gilad Arnoldcb638912013-06-24 04:57:11 -0700984 args = (payload_checker.payload.manifest.install_operations, report,
985 'foo', 0, rootfs_part_size, rootfs_part_size, 0, False)
Allie Woodfb04d302015-04-03 14:25:48 -0700986 if fail_nonexhaustive_full_update:
Gilad Arnold5502b562013-03-08 13:22:31 -0800987 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -0700988 payload_checker._CheckOperations, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -0800989 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -0700990 self.assertEqual(rootfs_data_length,
991 payload_checker._CheckOperations(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -0800992
993 def DoCheckSignaturesTest(self, fail_empty_sigs_blob, fail_missing_pseudo_op,
994 fail_mismatched_pseudo_op, fail_sig_missing_fields,
995 fail_unknown_sig_version, fail_incorrect_sig):
996 # Generate a test payload. For this test, we only care about the signature
997 # block and how it relates to the payload hash. Therefore, we're generating
998 # a random (otherwise useless) payload for this purpose.
999 payload_gen = test_utils.EnhancedPayloadGenerator()
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001000 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -08001001 payload_gen.SetBlockSize(block_size)
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001002 rootfs_part_size = test_utils.MiB(2)
1003 kernel_part_size = test_utils.KiB(16)
Gilad Arnold5502b562013-03-08 13:22:31 -08001004 payload_gen.SetPartInfo(False, True, rootfs_part_size,
1005 hashlib.sha256('fake-new-rootfs-content').digest())
Gilad Arnold382df5c2013-05-03 12:49:28 -07001006 payload_gen.SetPartInfo(True, True, kernel_part_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001007 hashlib.sha256('fake-new-kernel-content').digest())
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001008 payload_gen.SetMinorVersion(0)
Gilad Arnold5502b562013-03-08 13:22:31 -08001009 payload_gen.AddOperationWithData(
1010 False, common.OpType.REPLACE,
1011 dst_extents=[(0, rootfs_part_size / block_size)],
1012 data_blob=os.urandom(rootfs_part_size))
1013
1014 do_forge_pseudo_op = (fail_missing_pseudo_op or fail_mismatched_pseudo_op)
1015 do_forge_sigs_data = (do_forge_pseudo_op or fail_empty_sigs_blob or
1016 fail_sig_missing_fields or fail_unknown_sig_version
1017 or fail_incorrect_sig)
1018
1019 sigs_data = None
1020 if do_forge_sigs_data:
1021 sigs_gen = test_utils.SignaturesGenerator()
1022 if not fail_empty_sigs_blob:
1023 if fail_sig_missing_fields:
1024 sig_data = None
1025 else:
1026 sig_data = test_utils.SignSha256('fake-payload-content',
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001027 test_utils._PRIVKEY_FILE_NAME)
Gilad Arnold5502b562013-03-08 13:22:31 -08001028 sigs_gen.AddSig(5 if fail_unknown_sig_version else 1, sig_data)
1029
1030 sigs_data = sigs_gen.ToBinary()
1031 payload_gen.SetSignatures(payload_gen.curr_offset, len(sigs_data))
1032
1033 if do_forge_pseudo_op:
1034 assert sigs_data is not None, 'should have forged signatures blob by now'
1035 sigs_len = len(sigs_data)
1036 payload_gen.AddOperation(
1037 False, common.OpType.REPLACE,
1038 data_offset=payload_gen.curr_offset / 2,
1039 data_length=sigs_len / 2,
1040 dst_extents=[(0, (sigs_len / 2 + block_size - 1) / block_size)])
1041
1042 # Generate payload (complete w/ signature) and create the test object.
1043 payload_checker = _GetPayloadChecker(
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001044 payload_gen.WriteToFileWithData,
1045 payload_gen_dargs={
1046 'sigs_data': sigs_data,
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001047 'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001048 'do_add_pseudo_operation': not do_forge_pseudo_op})
Gilad Arnold5502b562013-03-08 13:22:31 -08001049 payload_checker.payload_type = checker._TYPE_FULL
1050 report = checker._PayloadReport()
1051
1052 # We have to check the manifest first in order to set signature attributes.
Gilad Arnold382df5c2013-05-03 12:49:28 -07001053 payload_checker._CheckManifest(report, rootfs_part_size, kernel_part_size)
Gilad Arnold5502b562013-03-08 13:22:31 -08001054
1055 should_fail = (fail_empty_sigs_blob or fail_missing_pseudo_op or
1056 fail_mismatched_pseudo_op or fail_sig_missing_fields or
1057 fail_unknown_sig_version or fail_incorrect_sig)
Gilad Arnoldcb638912013-06-24 04:57:11 -07001058 args = (report, test_utils._PUBKEY_FILE_NAME)
Gilad Arnold5502b562013-03-08 13:22:31 -08001059 if should_fail:
1060 self.assertRaises(update_payload.PayloadError,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001061 payload_checker._CheckSignatures, *args)
Gilad Arnold5502b562013-03-08 13:22:31 -08001062 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001063 self.assertIsNone(payload_checker._CheckSignatures(*args))
Gilad Arnold5502b562013-03-08 13:22:31 -08001064
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001065 def DoCheckManifestMinorVersionTest(self, minor_version, payload_type):
1066 """Parametric testing for CheckManifestMinorVersion().
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001067
1068 Args:
1069 minor_version: The payload minor version to test with.
1070 payload_type: The type of the payload we're testing, delta or full.
1071 """
1072 # Create the test object.
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001073 payload = self.MockPayload()
1074 payload.manifest.minor_version = minor_version
1075 payload_checker = checker.PayloadChecker(payload)
1076 payload_checker.payload_type = payload_type
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001077 report = checker._PayloadReport()
1078
1079 should_succeed = (
1080 (minor_version == 0 and payload_type == checker._TYPE_FULL) or
1081 (minor_version == 1 and payload_type == checker._TYPE_DELTA) or
1082 (minor_version == 2 and payload_type == checker._TYPE_DELTA))
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001083 args = (report,)
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001084
1085 if should_succeed:
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001086 self.assertIsNone(payload_checker._CheckManifestMinorVersion(*args))
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001087 else:
1088 self.assertRaises(update_payload.PayloadError,
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001089 payload_checker._CheckManifestMinorVersion, *args)
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001090
Gilad Arnold06eea332015-07-13 18:06:33 -07001091 def DoRunTest(self, rootfs_part_size_provided, kernel_part_size_provided,
1092 fail_wrong_payload_type, fail_invalid_block_size,
1093 fail_mismatched_block_size, fail_excess_data,
1094 fail_rootfs_part_size_exceeded,
1095 fail_kernel_part_size_exceeded):
Gilad Arnold5502b562013-03-08 13:22:31 -08001096 # Generate a test payload. For this test, we generate a full update that
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001097 # has sample kernel and rootfs operations. Since most testing is done with
Gilad Arnold5502b562013-03-08 13:22:31 -08001098 # internal PayloadChecker methods that are tested elsewhere, here we only
1099 # tamper with what's actually being manipulated and/or tested in the Run()
1100 # method itself. Note that the checker doesn't verify partition hashes, so
1101 # they're safe to fake.
1102 payload_gen = test_utils.EnhancedPayloadGenerator()
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001103 block_size = test_utils.KiB(4)
Gilad Arnold5502b562013-03-08 13:22:31 -08001104 payload_gen.SetBlockSize(block_size)
Gilad Arnold06eea332015-07-13 18:06:33 -07001105 kernel_filesystem_size = test_utils.KiB(16)
1106 rootfs_filesystem_size = test_utils.MiB(2)
1107 payload_gen.SetPartInfo(False, True, rootfs_filesystem_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001108 hashlib.sha256('fake-new-rootfs-content').digest())
Gilad Arnold06eea332015-07-13 18:06:33 -07001109 payload_gen.SetPartInfo(True, True, kernel_filesystem_size,
Gilad Arnold5502b562013-03-08 13:22:31 -08001110 hashlib.sha256('fake-new-kernel-content').digest())
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001111 payload_gen.SetMinorVersion(0)
Gilad Arnold06eea332015-07-13 18:06:33 -07001112
1113 rootfs_part_size = 0
1114 if rootfs_part_size_provided:
1115 rootfs_part_size = rootfs_filesystem_size + block_size
1116 rootfs_op_size = rootfs_part_size or rootfs_filesystem_size
1117 if fail_rootfs_part_size_exceeded:
1118 rootfs_op_size += block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001119 payload_gen.AddOperationWithData(
1120 False, common.OpType.REPLACE,
Gilad Arnold06eea332015-07-13 18:06:33 -07001121 dst_extents=[(0, rootfs_op_size / block_size)],
1122 data_blob=os.urandom(rootfs_op_size))
1123
1124 kernel_part_size = 0
1125 if kernel_part_size_provided:
1126 kernel_part_size = kernel_filesystem_size + block_size
1127 kernel_op_size = kernel_part_size or kernel_filesystem_size
1128 if fail_kernel_part_size_exceeded:
1129 kernel_op_size += block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001130 payload_gen.AddOperationWithData(
1131 True, common.OpType.REPLACE,
Gilad Arnold06eea332015-07-13 18:06:33 -07001132 dst_extents=[(0, kernel_op_size / block_size)],
1133 data_blob=os.urandom(kernel_op_size))
Gilad Arnold5502b562013-03-08 13:22:31 -08001134
1135 # Generate payload (complete w/ signature) and create the test object.
Gilad Arnold5502b562013-03-08 13:22:31 -08001136 if fail_invalid_block_size:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001137 use_block_size = block_size + 5 # Not a power of two.
Gilad Arnold5502b562013-03-08 13:22:31 -08001138 elif fail_mismatched_block_size:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001139 use_block_size = block_size * 2 # Different that payload stated.
Gilad Arnold5502b562013-03-08 13:22:31 -08001140 else:
1141 use_block_size = block_size
Gilad Arnold5502b562013-03-08 13:22:31 -08001142
Gilad Arnoldcb638912013-06-24 04:57:11 -07001143 kwargs = {
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001144 'payload_gen_dargs': {
Gilad Arnold18f4f9f2013-04-02 16:24:41 -07001145 'privkey_file_name': test_utils._PRIVKEY_FILE_NAME,
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001146 'do_add_pseudo_operation': True,
1147 'is_pseudo_in_kernel': True,
1148 'padding': os.urandom(1024) if fail_excess_data else None},
1149 'checker_init_dargs': {
1150 'assert_type': 'delta' if fail_wrong_payload_type else 'full',
1151 'block_size': use_block_size}}
1152 if fail_invalid_block_size:
1153 self.assertRaises(update_payload.PayloadError, _GetPayloadChecker,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001154 payload_gen.WriteToFileWithData, **kwargs)
Gilad Arnold5502b562013-03-08 13:22:31 -08001155 else:
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001156 payload_checker = _GetPayloadChecker(payload_gen.WriteToFileWithData,
Gilad Arnoldcb638912013-06-24 04:57:11 -07001157 **kwargs)
Gilad Arnold06eea332015-07-13 18:06:33 -07001158
1159 kwargs = {'pubkey_file_name': test_utils._PUBKEY_FILE_NAME,
1160 'rootfs_part_size': rootfs_part_size,
1161 'kernel_part_size': kernel_part_size}
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001162 should_fail = (fail_wrong_payload_type or fail_mismatched_block_size or
Gilad Arnold06eea332015-07-13 18:06:33 -07001163 fail_excess_data or
1164 fail_rootfs_part_size_exceeded or
1165 fail_kernel_part_size_exceeded)
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001166 if should_fail:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001167 self.assertRaises(update_payload.PayloadError, payload_checker.Run,
1168 **kwargs)
Gilad Arnoldeaed0d12013-04-30 15:38:22 -07001169 else:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001170 self.assertIsNone(payload_checker.Run(**kwargs))
Gilad Arnold5502b562013-03-08 13:22:31 -08001171
Gilad Arnold5502b562013-03-08 13:22:31 -08001172# This implements a generic API, hence the occasional unused args.
1173# pylint: disable=W0613
1174def ValidateCheckOperationTest(op_type_name, is_last, allow_signature,
1175 allow_unhashed, fail_src_extents,
1176 fail_dst_extents,
1177 fail_mismatched_data_offset_length,
1178 fail_missing_dst_extents, fail_src_length,
1179 fail_dst_length, fail_data_hash,
Allie Wood7cf9f132015-02-26 14:28:19 -08001180 fail_prev_data_offset, fail_bad_minor_version):
Gilad Arnold5502b562013-03-08 13:22:31 -08001181 """Returns True iff the combination of arguments represents a valid test."""
1182 op_type = _OpTypeByName(op_type_name)
1183
Allie Wood7cf9f132015-02-26 14:28:19 -08001184 # REPLACE/REPLACE_BZ operations don't read data from src partition. They are
1185 # compatible with all valid minor versions, so we don't need to check that.
Gilad Arnold5502b562013-03-08 13:22:31 -08001186 if (op_type in (common.OpType.REPLACE, common.OpType.REPLACE_BZ) and (
Allie Wood7cf9f132015-02-26 14:28:19 -08001187 fail_src_extents or fail_src_length or fail_bad_minor_version)):
Gilad Arnold5502b562013-03-08 13:22:31 -08001188 return False
1189
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001190 # MOVE and SOURCE_COPY operations don't carry data.
1191 if (op_type in (common.OpType.MOVE, common.OpType.SOURCE_COPY) and (
Gilad Arnold5502b562013-03-08 13:22:31 -08001192 fail_mismatched_data_offset_length or fail_data_hash or
1193 fail_prev_data_offset)):
1194 return False
1195
1196 return True
1197
1198
1199def TestMethodBody(run_method_name, run_dargs):
1200 """Returns a function that invokes a named method with named arguments."""
1201 return lambda self: getattr(self, run_method_name)(**run_dargs)
1202
1203
1204def AddParametricTests(tested_method_name, arg_space, validate_func=None):
1205 """Enumerates and adds specific parametric tests to PayloadCheckerTest.
1206
1207 This function enumerates a space of test parameters (defined by arg_space),
1208 then binds a new, unique method name in PayloadCheckerTest to a test function
1209 that gets handed the said parameters. This is a preferable approach to doing
1210 the enumeration and invocation during the tests because this way each test is
1211 treated as a complete run by the unittest framework, and so benefits from the
1212 usual setUp/tearDown mechanics.
1213
1214 Args:
Gilad Arnoldcb638912013-06-24 04:57:11 -07001215 tested_method_name: Name of the tested PayloadChecker method.
1216 arg_space: A dictionary containing variables (keys) and lists of values
1217 (values) associated with them.
1218 validate_func: A function used for validating test argument combinations.
Gilad Arnold5502b562013-03-08 13:22:31 -08001219 """
1220 for value_tuple in itertools.product(*arg_space.itervalues()):
1221 run_dargs = dict(zip(arg_space.iterkeys(), value_tuple))
1222 if validate_func and not validate_func(**run_dargs):
1223 continue
1224 run_method_name = 'Do%sTest' % tested_method_name
1225 test_method_name = 'test%s' % tested_method_name
1226 for arg_key, arg_val in run_dargs.iteritems():
1227 if arg_val or type(arg_val) is int:
1228 test_method_name += '__%s=%s' % (arg_key, arg_val)
1229 setattr(PayloadCheckerTest, test_method_name,
1230 TestMethodBody(run_method_name, run_dargs))
1231
1232
1233def AddAllParametricTests():
1234 """Enumerates and adds all parametric tests to PayloadCheckerTest."""
1235 # Add all _CheckElem() test cases.
1236 AddParametricTests('AddElem',
1237 {'linebreak': (True, False),
1238 'indent': (0, 1, 2),
1239 'convert': (str, lambda s: s[::-1]),
1240 'is_present': (True, False),
1241 'is_mandatory': (True, False),
1242 'is_submsg': (True, False)})
1243
1244 # Add all _Add{Mandatory,Optional}Field tests.
1245 AddParametricTests('AddField',
1246 {'is_mandatory': (True, False),
1247 'linebreak': (True, False),
1248 'indent': (0, 1, 2),
1249 'convert': (str, lambda s: s[::-1]),
1250 'is_present': (True, False)})
1251
1252 # Add all _Add{Mandatory,Optional}SubMsg tests.
1253 AddParametricTests('AddSubMsg',
1254 {'is_mandatory': (True, False),
1255 'is_present': (True, False)})
1256
1257 # Add all _CheckManifest() test cases.
1258 AddParametricTests('CheckManifest',
1259 {'fail_mismatched_block_size': (True, False),
1260 'fail_bad_sigs': (True, False),
1261 'fail_mismatched_oki_ori': (True, False),
1262 'fail_bad_oki': (True, False),
1263 'fail_bad_ori': (True, False),
1264 'fail_bad_nki': (True, False),
1265 'fail_bad_nri': (True, False),
Gilad Arnold382df5c2013-05-03 12:49:28 -07001266 'fail_old_kernel_fs_size': (True, False),
1267 'fail_old_rootfs_fs_size': (True, False),
1268 'fail_new_kernel_fs_size': (True, False),
1269 'fail_new_rootfs_fs_size': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001270
1271 # Add all _CheckOperation() test cases.
1272 AddParametricTests('CheckOperation',
1273 {'op_type_name': ('REPLACE', 'REPLACE_BZ', 'MOVE',
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001274 'BSDIFF', 'SOURCE_COPY',
1275 'SOURCE_BSDIFF'),
Gilad Arnold5502b562013-03-08 13:22:31 -08001276 'is_last': (True, False),
1277 'allow_signature': (True, False),
1278 'allow_unhashed': (True, False),
1279 'fail_src_extents': (True, False),
1280 'fail_dst_extents': (True, False),
1281 'fail_mismatched_data_offset_length': (True, False),
1282 'fail_missing_dst_extents': (True, False),
1283 'fail_src_length': (True, False),
1284 'fail_dst_length': (True, False),
1285 'fail_data_hash': (True, False),
Allie Wood7cf9f132015-02-26 14:28:19 -08001286 'fail_prev_data_offset': (True, False),
1287 'fail_bad_minor_version': (True, False)},
Gilad Arnold5502b562013-03-08 13:22:31 -08001288 validate_func=ValidateCheckOperationTest)
1289
1290 # Add all _CheckOperations() test cases.
1291 AddParametricTests('CheckOperations',
Allie Woodfb04d302015-04-03 14:25:48 -07001292 {'fail_nonexhaustive_full_update': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001293
1294 # Add all _CheckOperations() test cases.
1295 AddParametricTests('CheckSignatures',
1296 {'fail_empty_sigs_blob': (True, False),
1297 'fail_missing_pseudo_op': (True, False),
1298 'fail_mismatched_pseudo_op': (True, False),
1299 'fail_sig_missing_fields': (True, False),
1300 'fail_unknown_sig_version': (True, False),
1301 'fail_incorrect_sig': (True, False)})
1302
Gilad Arnold0d575cd2015-07-13 17:29:21 -07001303 # Add all _CheckManifestMinorVersion() test cases.
1304 AddParametricTests('CheckManifestMinorVersion',
1305 {'minor_version': (None, 0, 1, 2, 555),
Allie Woodf5c4f3e2015-02-20 16:57:46 -08001306 'payload_type': (checker._TYPE_FULL,
1307 checker._TYPE_DELTA)})
1308
Gilad Arnold5502b562013-03-08 13:22:31 -08001309 # Add all Run() test cases.
1310 AddParametricTests('Run',
Gilad Arnold06eea332015-07-13 18:06:33 -07001311 {'rootfs_part_size_provided': (True, False),
1312 'kernel_part_size_provided': (True, False),
1313 'fail_wrong_payload_type': (True, False),
Gilad Arnold5502b562013-03-08 13:22:31 -08001314 'fail_invalid_block_size': (True, False),
1315 'fail_mismatched_block_size': (True, False),
Gilad Arnold06eea332015-07-13 18:06:33 -07001316 'fail_excess_data': (True, False),
1317 'fail_rootfs_part_size_exceeded': (True, False),
1318 'fail_kernel_part_size_exceeded': (True, False)})
Gilad Arnold5502b562013-03-08 13:22:31 -08001319
1320
1321if __name__ == '__main__':
1322 AddAllParametricTests()
1323 unittest.main()