blob: ec703407182eb9c7aae7a799d7049ab83e3db964 [file] [log] [blame]
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Image API unittests."""
import os
from pathlib import Path
from chromite.lib import constants
from chromite.lib import chroot_lib
from chromite.lib import cros_build_lib
from chromite.lib import cros_test_lib
from chromite.lib import image_lib
from chromite.lib import osutils
from chromite.lib import sysroot_lib
from chromite.service import image
class BuildImageTest(cros_test_lib.RunCommandTempDirTestCase):
"""Build Image tests."""
def setUp(self):
osutils.Touch(os.path.join(self.tempdir,
image.PARALLEL_EMERGE_STATUS_FILE_NAME))
self.PatchObject(osutils.TempDir, '__enter__', return_value=self.tempdir)
def testInsideChrootCommand(self):
"""Test the build_image command when called from inside the chroot."""
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
image.Build('board', [constants.IMAGE_TYPE_BASE])
self.assertCommandContains(
[os.path.join(constants.CROSUTILS_DIR, 'build_image')])
def testOutsideChrootCommand(self):
"""Test the build_image command when called from outside the chroot."""
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
image.Build('board', [constants.IMAGE_TYPE_BASE])
self.assertCommandContains(['./build_image'])
def testBuildBoardHandling(self):
"""Test the argument handling."""
# No board should raise an error.
with self.assertRaises(image.InvalidArgumentError):
image.Build(None, [constants.IMAGE_TYPE_BASE])
with self.assertRaises(image.InvalidArgumentError):
image.Build('', [constants.IMAGE_TYPE_BASE])
# Should be using the passed board.
image.Build('board', [constants.IMAGE_TYPE_BASE])
self.assertCommandContains(['--board', 'board'])
def testBuildImageTypes(self):
"""Test the image type handling."""
result = image.Build('board', [])
assert result.all_built and not result.build_run
# Should be using the argument when passed.
image.Build('board', [constants.IMAGE_TYPE_DEV])
self.assertCommandContains([constants.IMAGE_TYPE_DEV])
# Multiple should all be passed.
multi = [constants.IMAGE_TYPE_BASE, constants.IMAGE_TYPE_DEV,
constants.IMAGE_TYPE_TEST]
image.Build('board', multi)
self.assertCommandContains(multi)
# Building RECOVERY only should cause base to be built.
image.Build('board', [constants.IMAGE_TYPE_RECOVERY])
self.assertCommandContains([constants.IMAGE_TYPE_BASE])
class BuildConfigTest(cros_test_lib.MockTestCase):
"""BuildConfig tests."""
def testGetArguments(self):
"""GetArguments tests."""
config = image.BuildConfig()
self.assertEqual([], config.GetArguments())
# Make sure each arg produces the correct argument individually.
config.builder_path = 'test'
self.assertEqual(['--builder_path', 'test'], config.GetArguments())
config.builder_path = None
config.disk_layout = 'disk'
self.assertEqual(['--disk_layout', 'disk'], config.GetArguments())
config.disk_layout = None
config.enable_rootfs_verification = False
self.assertEqual(['--noenable_rootfs_verification'], config.GetArguments())
config.enable_rootfs_verification = True
config.replace = True
self.assertEqual(['--replace'], config.GetArguments())
config.replace = False
config.version = 'version'
self.assertEqual(['--version', 'version'], config.GetArguments())
config.version = None
class CreateVmTest(cros_test_lib.RunCommandTestCase):
"""Create VM tests."""
def setUp(self):
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
def testNoBoardFails(self):
"""Should fail when not given a valid board-ish value."""
with self.assertRaises(AssertionError):
image.CreateVm('')
def testBoardArgument(self):
"""Test the board argument."""
image.CreateVm('board')
self.assertCommandContains(['--board', 'board'])
def testTestImage(self):
"""Test the application of the --test_image argument."""
image.CreateVm('board', is_test=True)
self.assertCommandContains(['--test_image'])
def testNonTestImage(self):
"""Test the non-application of the --test_image argument."""
image.CreateVm('board', is_test=False)
self.assertCommandContains(['--test_image'], expected=False)
def testDiskLayout(self):
"""Test the application of the --disk_layout argument."""
image.CreateVm('board', disk_layout='5000PB')
self.assertCommandContains(['--disk_layout', '5000PB'])
def testCommandError(self):
"""Test handling of an error when running the command."""
self.rc.SetDefaultCmdResult(returncode=1)
with self.assertRaises(image.ImageToVmError):
image.CreateVm('board')
def testResultPath(self):
"""Test the path building."""
self.PatchObject(image_lib, 'GetLatestImageLink', return_value='/tmp')
self.assertEqual(os.path.join('/tmp', constants.VM_IMAGE_BIN),
image.CreateVm('board'))
class BuildRecoveryTest(cros_test_lib.RunCommandTestCase):
"""Create recovery image tests."""
def setUp(self):
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
def testNoBoardFails(self):
"""Should fail when not given a valid board-ish value."""
with self.assertRaises(image.InvalidArgumentError):
image.BuildRecoveryImage('')
def testBoardArgument(self):
"""Test the board argument."""
image.BuildRecoveryImage('board')
self.assertCommandContains(['--board', 'board'])
class ImageTestTest(cros_test_lib.RunCommandTempDirTestCase):
"""Image Test tests."""
def setUp(self):
"""Setup the filesystem."""
self.board = 'board'
self.chroot_container = os.path.join(self.tempdir, 'outside')
self.outside_result_dir = os.path.join(self.chroot_container, 'results')
self.inside_result_dir_inside = '/inside/results_inside'
self.inside_result_dir_outside = os.path.join(self.chroot_container,
'inside/results_inside')
self.image_dir_inside = '/inside/build/board/latest'
self.image_dir_outside = os.path.join(self.chroot_container,
'inside/build/board/latest')
D = cros_test_lib.Directory
filesystem = (
D('outside', (
D('results', ()),
D('inside', (
D('results_inside', ()),
D('build', (
D('board', (
D('latest', ('%s.bin' % constants.BASE_IMAGE_NAME,)),
)),
)),
)),
)),
)
cros_test_lib.CreateOnDiskHierarchy(self.tempdir, filesystem)
def testTestFailsInvalidArguments(self):
"""Test invalid arguments are correctly failed."""
with self.assertRaises(image.InvalidArgumentError):
image.Test(None, None)
with self.assertRaises(image.InvalidArgumentError):
image.Test('', '')
with self.assertRaises(image.InvalidArgumentError):
image.Test(None, self.outside_result_dir)
with self.assertRaises(image.InvalidArgumentError):
image.Test(self.board, None)
def testTestInsideChrootAllProvided(self):
"""Test behavior when inside the chroot and all paths provided."""
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
image.Test(self.board, self.outside_result_dir,
image_dir=self.image_dir_inside)
# Inside chroot shouldn't need to do any path manipulations, so we should
# see exactly what we called it with.
self.assertCommandContains(['--board', self.board,
'--test_results_root', self.outside_result_dir,
self.image_dir_inside])
def testTestInsideChrootNoImageDir(self):
"""Test image dir generation inside the chroot."""
mocked_dir = '/foo/bar'
self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
self.PatchObject(image_lib, 'GetLatestImageLink', return_value=mocked_dir)
image.Test(self.board, self.outside_result_dir)
self.assertCommandContains(['--board', self.board,
'--test_results_root', self.outside_result_dir,
mocked_dir])
class TestCreateFactoryImageZip(cros_test_lib.MockTempDirTestCase):
"""Unittests for create_factory_image_zip."""
def setUp(self):
# Create a chroot_path.
self.chroot_path = os.path.join(self.tempdir, 'chroot_dir')
self.chroot = chroot_lib.Chroot(path=self.chroot_path)
self.sysroot_path = os.path.join(self.chroot_path, 'build', 'target')
self.sysroot = sysroot_lib.Sysroot(path=self.sysroot_path)
# Create appropriate sysroot structure.
osutils.SafeMakedirs(self.sysroot_path)
factory_bundle_path = self.chroot.full_path(self.sysroot.path, 'usr',
'local','factory', 'bundle')
osutils.SafeMakedirs(factory_bundle_path)
osutils.Touch(os.path.join(factory_bundle_path, 'bundle_foo'))
# Create factory shim directory.
self.factory_shim_path = os.path.join(self.tempdir, 'factory_shim_dir')
osutils.SafeMakedirs(self.factory_shim_path)
osutils.Touch(os.path.join(self.factory_shim_path, 'factory_install.bin'))
osutils.Touch(os.path.join(self.factory_shim_path, 'partition'))
osutils.SafeMakedirs(os.path.join(self.factory_shim_path, 'netboot'))
osutils.Touch(os.path.join(self.factory_shim_path, 'netboot', 'bar'))
# Create output dir.
self.output_dir = os.path.join(self.tempdir, 'output_dir')
osutils.SafeMakedirs(self.output_dir)
def test(self):
"""create_factory_image_zip calls cbuildbot/commands with correct args."""
version = '1.2.3.4'
output_file = image.create_factory_image_zip(self.chroot, self.sysroot,
Path(self.factory_shim_path), version, self.output_dir)
# Check that all expected files are present.
zip_contents = cros_build_lib.run(['zipinfo', '-1', output_file],
cwd=self.output_dir, stdout=True)
zip_files = sorted(zip_contents.output.decode('UTF-8').strip().split('\n'))
expected_files = sorted([
'factory_shim_dir/netboot/',
'factory_shim_dir/netboot/bar',
'factory_shim_dir/factory_install.bin',
'factory_shim_dir/partition',
'bundle_foo',
'BUILD_VERSION',
])
self.assertListEqual(zip_files, expected_files)
# Check contents of BUILD_VERSION.
cmd = ['unzip', '-p', output_file, 'BUILD_VERSION']
version_file = cros_build_lib.run(cmd, cwd=self.output_dir, stdout=True)
self.assertEqual(version_file.output.decode('UTF-8').strip(), version)