blob: 6e589ffdcd2f9fd62cb2543fa9b7dc94751b42d0 [file] [log] [blame] [edit]
# Copyright 2020 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for dlc_lib."""
import itertools
import json
import os
from unittest import mock
from chromite.lib import cros_test_lib
from chromite.lib import dlc_allowlist
from chromite.lib import dlc_lib
from chromite.lib import osutils
from chromite.lib import partial_mock
from chromite.scripts import cros_set_lsb_release
_PRE_ALLOCATED_BLOCKS = 100
_VERSION = "1.0"
_ID = "id"
_ID_FOO = "id-foo"
_PACKAGE = "package"
_NAME = "name"
_DESCRIPTION = "description"
_BOARD = "test_board"
_FULLNAME_REV = None
_BLOCK_SIZE = 4096
_IMAGE_SIZE_NEARING_RATIO = 1.05
_IMAGE_SIZE_GROWTH_RATIO = 1.2
_DAYS_TO_PURGE = 3
_DLC_LOADPIN_FILE_HEADER = "# LOADPIN_TRUSTED_VERITY_ROOT_DIGESTS"
# pylint: disable=protected-access
class UtilsTest(cros_test_lib.TempDirTestCase):
"""Tests dlc_lib utility functions."""
def testHashFile(self):
"""Test the hash of a simple file."""
file_path = os.path.join(self.tempdir, "f.txt")
osutils.WriteFile(file_path, "0123")
hash_value = dlc_lib.HashFile(file_path)
self.assertEqual(
hash_value,
"1be2e452b46d7a0d9656bbb1f768e824"
"8eba1b75baed65f5d99eafa948899a6a",
)
def testValidateDlcIdentifier(self):
"""Tests dlc_lib.ValidateDlcIdentifier."""
dlc_lib.ValidateDlcIdentifier("hello-world")
dlc_lib.ValidateDlcIdentifier("hello-world2")
dlc_lib.ValidateDlcIdentifier(
"this-string-has-length-40-exactly-now---"
)
self.assertRaises(Exception, dlc_lib.ValidateDlcIdentifier, "")
self.assertRaises(Exception, dlc_lib.ValidateDlcIdentifier, "-")
self.assertRaises(Exception, dlc_lib.ValidateDlcIdentifier, "-hi")
self.assertRaises(Exception, dlc_lib.ValidateDlcIdentifier, "hello%")
self.assertRaises(
Exception, dlc_lib.ValidateDlcIdentifier, "hello_world"
)
self.assertRaises(
Exception,
dlc_lib.ValidateDlcIdentifier,
"this-string-has-length-greater-than-40-now",
)
class EbuildParamsTest(cros_test_lib.MockTempDirTestCase):
"""Tests EbuildParams functions."""
def GetVaryingEbuildParams(self):
return {
"dlc_id": f"{_ID}_new",
"dlc_package": f"{_PACKAGE}_new",
"fs_type": dlc_lib.EXT4_TYPE,
"name": f"{_NAME}_new",
"description": f"{_DESCRIPTION}_new",
"pre_allocated_blocks": _PRE_ALLOCATED_BLOCKS * 2,
"version": f"{_VERSION}_new",
"preload": True,
"factory_install": False,
"loadpin_verity_digest": False,
"used_by": dlc_lib.USED_BY_USER,
"days_to_purge": _DAYS_TO_PURGE,
"mount_file_required": True,
"reserved": False,
"critical_update": False,
"scaled": True,
}
def testGetParamsPath(self):
"""Tests EbuildParams.GetParamsPath"""
install_root_dir = os.path.join(self.tempdir, "install_root_dir")
self.assertEqual(
dlc_lib.EbuildParams.GetParamsPath(
install_root_dir, _ID, _PACKAGE, False
),
os.path.join(
install_root_dir,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE,
dlc_lib.EBUILD_PARAMETERS,
),
)
self.assertEqual(
dlc_lib.EbuildParams.GetParamsPath(
install_root_dir, _ID, _PACKAGE, True
),
os.path.join(
install_root_dir,
dlc_lib.DLC_BUILD_DIR_SCALED,
_ID,
_PACKAGE,
dlc_lib.EBUILD_PARAMETERS,
),
)
def CheckParams(
self,
ebuild_params,
dlc_id=_ID,
dlc_package=_PACKAGE,
fs_type=dlc_lib.SQUASHFS_TYPE,
name=_NAME,
description=_DESCRIPTION,
pre_allocated_blocks=_PRE_ALLOCATED_BLOCKS,
version=_VERSION,
preload=False,
factory_install=False,
loadpin_verity_digest=False,
used_by=dlc_lib.USED_BY_SYSTEM,
days_to_purge=_DAYS_TO_PURGE,
mount_file_required=False,
reserved=False,
critical_update=False,
fullnamerev=_FULLNAME_REV,
scaled=False,
):
"""Tests EbuildParams JSON values"""
self.assertDictEqual(
ebuild_params,
{
"dlc_id": dlc_id,
"dlc_package": dlc_package,
"fs_type": fs_type,
"pre_allocated_blocks": pre_allocated_blocks,
"version": version,
"name": name,
"description": description,
"preload": preload,
"factory_install": factory_install,
"loadpin_verity_digest": loadpin_verity_digest,
"used_by": used_by,
"days_to_purge": days_to_purge,
"mount_file_required": mount_file_required,
"reserved": reserved,
"critical_update": critical_update,
"fullnamerev": fullnamerev,
"scaled": scaled,
},
)
def GenerateParams(
self,
install_root_dir,
dlc_id=_ID,
dlc_package=_PACKAGE,
fs_type=dlc_lib.SQUASHFS_TYPE,
name=_NAME,
description=_DESCRIPTION,
pre_allocated_blocks=_PRE_ALLOCATED_BLOCKS,
version=_VERSION,
preload=False,
factory_install=False,
loadpin_verity_digest=False,
used_by=dlc_lib.USED_BY_SYSTEM,
days_to_purge=_DAYS_TO_PURGE,
mount_file_required=False,
reserved=False,
critical_update=False,
fullnamerev=_FULLNAME_REV,
scaled=False,
) -> dlc_lib.EbuildParams:
"""Creates and Stores DLC params at install_root_dir"""
params = dlc_lib.EbuildParams(
dlc_id=dlc_id,
dlc_package=dlc_package,
fs_type=fs_type,
name=name,
description=description,
pre_allocated_blocks=pre_allocated_blocks,
version=version,
preload=preload,
factory_install=factory_install,
loadpin_verity_digest=loadpin_verity_digest,
used_by=used_by,
days_to_purge=days_to_purge,
mount_file_required=mount_file_required,
reserved=reserved,
critical_update=critical_update,
fullnamerev=fullnamerev,
scaled=scaled,
)
params.StoreDlcParameters(install_root_dir=install_root_dir, sudo=False)
return params
def testVerifyDlcParametersFactoryInstallable(self):
"""Tests EbuildParams.VerifyDlcParameters"""
dlc_allowlist_mock = self.PatchObject(
dlc_allowlist, "IsFactoryInstallAllowlisted", return_value=True
)
params = self.GenerateParams(os.path.join(self.tempdir, "build_root"))
params.dlc_id = "foo"
params.factory_install = True
params.VerifyDlcParameters()
dlc_allowlist_mock.assert_called_once_with(params.dlc_id)
def testVerifyDlcParametersNotAllowedToFactoryInstall(self):
"""Tests EbuildParams.VerifyDlcParameters"""
dlc_allowlist_mock = self.PatchObject(
dlc_allowlist, "IsFactoryInstallAllowlisted", return_value=False
)
params = self.GenerateParams(os.path.join(self.tempdir, "build_root"))
params.dlc_id = "foo"
params.factory_install = True
with self.assertRaises(Exception):
params.VerifyDlcParameters()
dlc_allowlist_mock.assert_called_once_with(params.dlc_id)
def testStoreDlcParameters(self):
"""Tests EbuildParams.StoreDlcParameters"""
sysroot = os.path.join(self.tempdir, "build_root")
self.GenerateParams(sysroot)
ebuild_params_path = os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE,
dlc_lib.EBUILD_PARAMETERS,
)
self.assertExists(ebuild_params_path)
with open(ebuild_params_path, "rb") as f:
self.CheckParams(json.load(f))
def testStoreVaryingDlcParameters(self):
"""Tests EbuildParams.StoreDlcParameters with non default values"""
sysroot = os.path.join(self.tempdir, "build_root")
params = self.GetVaryingEbuildParams()
self.GenerateParams(sysroot, **params)
ebuild_params_path = os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR_SCALED,
params["dlc_id"],
params["dlc_package"],
dlc_lib.EBUILD_PARAMETERS,
)
self.assertExists(ebuild_params_path)
with open(ebuild_params_path, "rb") as f:
self.CheckParams(json.load(f), **params)
def testLoadDlcParameters(self):
"""Tests EbuildParams.LoadDlcParameters"""
sysroot = os.path.join(self.tempdir, "build_root")
self.GenerateParams(sysroot)
ebuild_params_class = dlc_lib.EbuildParams.LoadEbuildParams(
sysroot,
_ID,
_PACKAGE,
False,
)
self.CheckParams(ebuild_params_class.__dict__)
def testLoadVaryingDlcParameters(self):
"""Tests EbuildParams.LoadDlcParameters"""
sysroot = os.path.join(self.tempdir, "build_root")
params = self.GetVaryingEbuildParams()
self.GenerateParams(sysroot, **params)
ebuild_params_class = dlc_lib.EbuildParams.LoadEbuildParams(
sysroot,
params["dlc_id"],
params["dlc_package"],
params["scaled"],
)
self.CheckParams(ebuild_params_class.__dict__, **params)
class DlcGeneratorTest(
cros_test_lib.LoggingTestCase, cros_test_lib.RunCommandTempDirTestCase
):
"""Tests DlcGenerator."""
def setUp(self):
self.ExpectRootOwnedFiles()
def GetDlcGenerator(self, fs_type=dlc_lib.SQUASHFS_TYPE):
"""Factory method for a DcGenerator object"""
src_dir = os.path.join(self.tempdir, "src")
osutils.SafeMakedirs(src_dir)
sysroot = os.path.join(self.tempdir, "build_root")
osutils.WriteFile(
os.path.join(sysroot, dlc_lib.LSB_RELEASE),
"%s=%s\n" % (cros_set_lsb_release.LSB_KEY_APPID_RELEASE, "foo"),
makedirs=True,
)
ue_conf = os.path.join(sysroot, "etc", "update_engine.conf")
osutils.WriteFile(ue_conf, "foo-content", makedirs=True)
params = dlc_lib.EbuildParams(
dlc_id=_ID,
dlc_package=_PACKAGE,
fs_type=fs_type,
name=_NAME,
description=_DESCRIPTION,
pre_allocated_blocks=_PRE_ALLOCATED_BLOCKS,
version=_VERSION,
preload=False,
factory_install=False,
used_by=dlc_lib.USED_BY_SYSTEM,
days_to_purge=_DAYS_TO_PURGE,
mount_file_required=False,
reserved=False,
critical_update=False,
fullnamerev=_FULLNAME_REV,
)
return dlc_lib.DlcGenerator(
ebuild_params=params, src_dir=src_dir, sysroot=sysroot, board=_BOARD
)
def testSquashOwnerships(self):
"""Test dlc_lib.SquashOwnershipsTest"""
self.GetDlcGenerator().SquashOwnerships(self.tempdir)
self.assertCommandContains(["chown", "-R", "0:0"])
self.assertCommandContains(["find"])
def testCreateExt4Image(self):
"""Test CreateExt4Image to make sure it runs with valid parameters."""
copy_dir_mock = self.PatchObject(osutils, "CopyDirContents")
mount_mock = self.PatchObject(osutils, "MountDir")
umount_mock = self.PatchObject(osutils, "UmountDir")
self.GetDlcGenerator(fs_type=dlc_lib.EXT4_TYPE).CreateExt4Image()
self.assertCommandContains(
["/sbin/mkfs.ext4", "-b", "4096", "-O", "^has_journal"]
)
self.assertCommandContains(["/sbin/e2fsck", "-y", "-f"])
self.assertCommandContains(["/sbin/resize2fs", "-M"])
copy_dir_mock.assert_called_once_with(
partial_mock.HasString("src"),
partial_mock.HasString("root"),
symlinks=True,
)
mount_mock.assert_called_once_with(
mock.ANY,
partial_mock.HasString("mount_point"),
mount_opts=("loop", "rw"),
)
umount_mock.assert_called_once_with(
partial_mock.HasString("mount_point")
)
def testCreateSquashfsImage(self):
"""Verify creating squashfs commands are run with correct parameters."""
self.PatchObject(os.path, "getsize", return_value=(_BLOCK_SIZE * 2))
copy_dir_mock = self.PatchObject(osutils, "CopyDirContents")
self.GetDlcGenerator().CreateSquashfsImage()
self.assertCommandContains(["mksquashfs", "-4k-align", "-noappend"])
copy_dir_mock.assert_called_once_with(
partial_mock.HasString("src"),
partial_mock.HasString("root"),
symlinks=True,
)
def testCreateSquashfsImagePageAlignment(self):
"""Test that creating squashfs commands are run with page alignment."""
self.PatchObject(os.path, "getsize", return_value=(_BLOCK_SIZE * 1))
truncate_mock = self.PatchObject(os, "truncate")
copy_dir_mock = self.PatchObject(osutils, "CopyDirContents")
self.GetDlcGenerator().CreateSquashfsImage()
self.assertCommandContains(["mksquashfs", "-4k-align", "-noappend"])
truncate_mock.asset_called()
copy_dir_mock.assert_called_once_with(
partial_mock.HasString("src"),
partial_mock.HasString("root"),
symlinks=True,
)
def testPrepareLsbRelease(self):
"""Tests that lsb-release is created correctly."""
generator = self.GetDlcGenerator()
dlc_dir = os.path.join(self.tempdir, "dlc_dir")
generator.PrepareLsbRelease(dlc_dir)
expected_lsb_release = (
"\n".join(
[
"DLC_ID=%s" % _ID,
"DLC_PACKAGE=%s" % _PACKAGE,
"DLC_NAME=%s" % _NAME,
"DLC_RELEASE_APPID=foo_%s" % _ID,
]
)
+ "\n"
)
self.assertEqual(
osutils.ReadFile(os.path.join(dlc_dir, "etc/lsb-release")),
expected_lsb_release,
)
def testCollectExtraResources(self):
"""Tests that extra resources are collected correctly."""
generator = self.GetDlcGenerator()
dlc_dir = os.path.join(self.tempdir, "dlc_dir")
generator.CollectExtraResources(dlc_dir)
ue_conf = "etc/update_engine.conf"
self.assertEqual(
osutils.ReadFile(os.path.join(self.tempdir, "build_root", ue_conf)),
"foo-content",
)
def testGetImageloaderJsonContent(self):
"""Test that GetImageloaderJsonContent returns correct content."""
blocks = 100
content = self.GetDlcGenerator().GetImageloaderJsonContent(
"01234567", "deadbeef", blocks
)
self.assertEqual(
content,
{
"fs-type": dlc_lib.SQUASHFS_TYPE,
"pre-allocated-size": str(_PRE_ALLOCATED_BLOCKS * _BLOCK_SIZE),
"id": _ID,
"package": _PACKAGE,
"size": str(blocks * _BLOCK_SIZE),
"table-sha256-hash": "deadbeef",
"name": _NAME,
"description": _DESCRIPTION,
"image-sha256-hash": "01234567",
"image-type": "dlc",
"version": _VERSION,
"is-removable": True,
"manifest-version": 1,
"mount-file-required": False,
"preload-allowed": False,
"factory-install": False,
"used-by": dlc_lib.USED_BY_SYSTEM,
"days-to-purge": _DAYS_TO_PURGE,
"reserved": False,
"critical-update": False,
"loadpin-verity-digest": False,
"scaled": False,
"use-logical-volume": False,
},
)
def testLogicalVolumeJson(self):
"""Test that GetImageloaderJsonContent logical volume value is set."""
gen = self.GetDlcGenerator()
# Values should always be what `scaled` is set to.
for pr in list(itertools.product((False, True), repeat=2)):
gen.ebuild_params.scaled = pr[0]
gen.ebuild_params.use_logical_volume = pr[1]
content = gen.GetImageloaderJsonContent("", "", 100)
self.assertEqual(content["scaled"], pr[0])
self.assertEqual(content["use-logical-volume"], pr[0])
def testVerifyImageSize(self):
"""Test that VerifyImageSize throws exception on errors only."""
# Succeeds since image size is smaller than preallocated size.
self.PatchObject(
os.path,
"getsize",
return_value=(_PRE_ALLOCATED_BLOCKS - 1) * _BLOCK_SIZE,
)
self.GetDlcGenerator().VerifyImageSize()
with self.assertRaises(ValueError):
# Fails since image size is bigger than preallocated size.
self.PatchObject(
os.path,
"getsize",
return_value=(_PRE_ALLOCATED_BLOCKS + 1) * _BLOCK_SIZE,
)
self.GetDlcGenerator().VerifyImageSize()
def testVerifyImageSizeNearingWarning(self):
"""Test that VerifyImageSize logs the correct nearing warning."""
# Logs a warning that actual size is near the preallocated size.
with cros_test_lib.LoggingCapturer() as logs:
self.PatchObject(
os.path,
"getsize",
return_value=(
_PRE_ALLOCATED_BLOCKS
* _BLOCK_SIZE
/ _IMAGE_SIZE_NEARING_RATIO
),
)
self.GetDlcGenerator().VerifyImageSize()
self.AssertLogsContain(logs, "is nearing the preallocated size")
def testVerifyImageSizeGrowthWarning(self):
"""Test that VerifyImageSize logs the correct growth warning."""
# Logs a warning that actual size is significantly less than the
# preallocated size.
with cros_test_lib.LoggingCapturer() as logs:
self.PatchObject(
os.path,
"getsize",
return_value=(
_PRE_ALLOCATED_BLOCKS
* _BLOCK_SIZE
/ _IMAGE_SIZE_GROWTH_RATIO
),
)
self.GetDlcGenerator().VerifyImageSize()
self.AssertLogsContain(
logs, "is significantly less than the preallocated size"
)
def testGetOptimalImageBlockSize(self):
"""Test that GetOptimalImageBlockSize returns the valid block size."""
dlc_generator = self.GetDlcGenerator()
self.assertEqual(dlc_generator.GetOptimalImageBlockSize(0), 0)
self.assertEqual(dlc_generator.GetOptimalImageBlockSize(1), 1)
self.assertEqual(dlc_generator.GetOptimalImageBlockSize(_BLOCK_SIZE), 1)
self.assertEqual(
dlc_generator.GetOptimalImageBlockSize(_BLOCK_SIZE + 1), 2
)
class FinalizeDlcsTest(cros_test_lib.MockTempDirTestCase):
"""Tests functions that generate the final DLC images."""
def setUp(self):
"""Setup FinalizeDlcsTest."""
self.ExpectRootOwnedFiles()
def testInstallDlcImagesLegacy(self):
"""Verify InstallDlcImages copies all legacy DLCs correctly."""
sysroot = os.path.join(self.tempdir, "sysroot")
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
dlc_lib.DLC_PACKAGE,
dlc_lib.DLC_IMAGE,
),
"content",
makedirs=True,
)
osutils.SafeMakedirs(
os.path.join(
sysroot, dlc_lib.DLC_BUILD_DIR, _ID, dlc_lib.DLC_PACKAGE
)
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD, sysroot=sysroot, install_root_dir=output
)
self.assertExists(
os.path.join(output, _ID, dlc_lib.DLC_PACKAGE, dlc_lib.DLC_IMAGE)
)
def testInstallDlcImagesScaled(self):
"""Verifies InstallDlcImages copies all scaled DLCs correctly."""
sysroot = os.path.join(self.tempdir, "sysroot")
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR_SCALED,
_ID,
dlc_lib.DLC_PACKAGE,
dlc_lib.DLC_IMAGE,
),
"content",
makedirs=True,
)
osutils.SafeMakedirs(
os.path.join(
sysroot, dlc_lib.DLC_BUILD_DIR_SCALED, _ID, dlc_lib.DLC_PACKAGE
)
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD,
sysroot=sysroot,
install_root_dir=output,
)
self.assertExists(
os.path.join(output, _ID, dlc_lib.DLC_PACKAGE, dlc_lib.DLC_IMAGE)
)
def testInstallDlcImagesAll(self):
"""Verifies InstallDlcImages copies all types of DLCs correctly."""
sysroot = os.path.join(self.tempdir, "sysroot")
for p, _id in (
(dlc_lib.DLC_BUILD_DIR, _ID),
(dlc_lib.DLC_BUILD_DIR_SCALED, _ID_FOO),
):
osutils.WriteFile(
os.path.join(
sysroot, p, _id, dlc_lib.DLC_PACKAGE, dlc_lib.DLC_IMAGE
),
"content",
makedirs=True,
)
osutils.SafeMakedirs(
os.path.join(sysroot, p, _id, dlc_lib.DLC_PACKAGE)
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD,
sysroot=sysroot,
install_root_dir=output,
)
self.assertExists(
os.path.join(output, _ID, dlc_lib.DLC_PACKAGE, dlc_lib.DLC_IMAGE)
)
self.assertExists(
os.path.join(
output, _ID_FOO, dlc_lib.DLC_PACKAGE, dlc_lib.DLC_IMAGE
)
)
def testInstallDlcImagesNoDlc(self):
copy_contents_mock = self.PatchObject(osutils, "CopyDirContents")
sysroot = os.path.join(self.tempdir, "sysroot")
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD, sysroot=sysroot, install_root_dir=output
)
copy_contents_mock.assert_not_called()
def testInstallDlcImagesWithPreloadAllowed(self):
package_nums = 2
preload_allowed_json = '{"preload-allowed": true}'
sysroot = os.path.join(self.tempdir, "sysroot")
for package_num in range(package_nums):
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE + str(package_num),
dlc_lib.DLC_IMAGE,
),
"image content",
makedirs=True,
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE + str(package_num),
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
preload_allowed_json,
makedirs=True,
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD, sysroot=sysroot, install_root_dir=output, preload=True
)
for package_num in range(package_nums):
self.assertExists(
os.path.join(
output, _ID, _PACKAGE + str(package_num), dlc_lib.DLC_IMAGE
)
)
def testInstallDlcImagesWithPreloadNotAllowed(self):
package_nums = 2
preload_not_allowed_json = '{"preload-allowed": false}'
sysroot = os.path.join(self.tempdir, "sysroot")
for package_num in range(package_nums):
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE + str(package_num),
dlc_lib.DLC_IMAGE,
),
"image content",
makedirs=True,
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE + str(package_num),
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
preload_not_allowed_json,
makedirs=True,
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(
board=_BOARD, sysroot=sysroot, install_root_dir=output, preload=True
)
for package_num in range(package_nums):
self.assertNotExists(
os.path.join(
output, _ID, _PACKAGE + str(package_num), dlc_lib.DLC_IMAGE
)
)
def testInstallDlcImagesTrustedVerityDigests(self):
"""Tests InstallDlcImages to verify verity digests are written."""
sysroot = self.tempdir / "sysroot"
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
'{"loadpin-verity-digest": true}',
makedirs=True,
)
root_hexdigest = (
"af7d331ac908dd6e4f6771a3146310bc7edcfe8d9794abcd34512e1a7b704adc"
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID,
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.DLC_VERITY_TABLE,
),
"0 128 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=128 "
f"alg=sha256 root_hexdigest={root_hexdigest} "
"salt="
"471347ffffff2f4a1cff1224ff7b04ffff68ff19ff2dffff63ff47ffffff387c",
makedirs=True,
)
output = os.path.join(self.tempdir, "output")
dlc_lib.InstallDlcImages(board=_BOARD, sysroot=sysroot, rootfs=output)
self.assertEqual(
osutils.ReadFile(
os.path.join(
output,
dlc_lib.DLC_META_DIR,
dlc_lib.DLC_LOADPIN_TRUSTED_VERITY_DIGESTS,
)
),
f"{_DLC_LOADPIN_FILE_HEADER}\n{root_hexdigest}\n",
)
def testInstallDlcImagesMultiDlcTrustedVerityDigests(self):
"""Verifies InstallDlcImages writes multiple verity digests."""
sysroot = self.tempdir / "sysroot"
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "1",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
'{"loadpin-verity-digest": true}',
makedirs=True,
)
root_hexdigest1 = (
"af7d331ac908dd6e4f6771a3146310bc7edcfe8d9794abcd34512e1a7b704adc"
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "1",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.DLC_VERITY_TABLE,
),
"0 128 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=128 "
f"alg=sha256 root_hexdigest={root_hexdigest1} "
"salt="
"471347ffffff2f4a1cff1224ff7b04ffff68ff19ff2dffff63ff47ffffff387c",
makedirs=True,
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "1dupe",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
'{"loadpin-verity-digest": true}',
makedirs=True,
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "1dupe",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.DLC_VERITY_TABLE,
),
"0 128 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=128 "
f"alg=sha256 root_hexdigest={root_hexdigest1} "
"salt="
"471347ffffff2f4a1cff1224ff7b04ffff68ff19ff2dffff63ff47ffffff387c",
makedirs=True,
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "2",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.IMAGELOADER_JSON,
),
'{"loadpin-verity-digest": true}',
makedirs=True,
)
root_hexdigest2 = (
"cdefedb2405a5d87a1e441caf0b3a6fd4d59947597149215ba9ef7d88e269004"
)
osutils.WriteFile(
os.path.join(
sysroot,
dlc_lib.DLC_BUILD_DIR,
_ID + "2",
_PACKAGE,
dlc_lib.DLC_TMP_META_DIR,
dlc_lib.DLC_VERITY_TABLE,
),
"0 196184 verity payload=ROOT_DEV hashtree=HASH_DEV "
"hashstart=196184 "
f"alg=sha256 root_hexdigest={root_hexdigest2} "
"salt="
"44ff73ff18ff59ff765aff4fffffff45ff2b60ffff2915ff3fffffffff3aff33",
makedirs=True,
)
output = self.tempdir / "output"
dlc_lib.InstallDlcImages(board=_BOARD, sysroot=sysroot, rootfs=output)
self.assertEqual(
osutils.ReadFile(
os.path.join(
output,
dlc_lib.DLC_META_DIR,
dlc_lib.DLC_LOADPIN_TRUSTED_VERITY_DIGESTS,
)
),
f"{_DLC_LOADPIN_FILE_HEADER}\n"
f"{root_hexdigest1}\n{root_hexdigest2}\n",
)