blob: 54bb1c460c9893e382c38f1880ec884d2f716d8d [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2012 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.
"""Unittests for build stages."""
import contextlib
import os
import sys
sys.path.insert(0, os.path.abspath('%s/../../..' % os.path.dirname(__file__)))
from chromite.cbuildbot import cbuildbot_config as config
from chromite.cbuildbot import cbuildbot_commands as commands
from chromite.cbuildbot import constants
from chromite.cbuildbot.stages import build_stages
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.lib import cros_build_lib
from chromite.lib import cros_build_lib_unittest
from chromite.lib import cros_test_lib
from chromite.lib import git
from chromite.lib import parallel
from chromite.lib import parallel_unittest
from chromite.lib import partial_mock
from chromite.cbuildbot.stages.generic_stages_unittest import patch
from chromite.cbuildbot.stages.generic_stages_unittest import patches
from chromite.cbuildbot.stages.generic_stages_unittest import BuilderRunMock
# pylint: disable=W0212,R0901
class InitSDKTest(generic_stages_unittest.RunCommandAbstractStageTest):
"""Test building the SDK"""
def setUp(self):
self.PatchObject(cros_build_lib, 'GetChrootVersion', return_value='12')
def ConstructStage(self):
return build_stages.InitSDKStage(self._run)
def testFullBuildWithExistingChroot(self):
"""Tests whether we create chroots for full builds."""
self._PrepareFull()
self._Run(dir_exists=True)
self.assertCommandContains(['cros_sdk'])
def testBinBuildWithMissingChroot(self):
"""Tests whether we create chroots when needed."""
self._PrepareBin()
# Do not force chroot replacement in build config.
self._run._config.chroot_replace = False
self._Run(dir_exists=False)
self.assertCommandContains(['cros_sdk'])
def testFullBuildWithMissingChroot(self):
"""Tests whether we create chroots when needed."""
self._PrepareFull()
self._Run(dir_exists=True)
self.assertCommandContains(['cros_sdk'])
def testFullBuildWithNoSDK(self):
"""Tests whether the --nosdk option works."""
self._PrepareFull(extra_cmd_args=['--nosdk'])
self._Run(dir_exists=False)
self.assertCommandContains(['cros_sdk', '--bootstrap'])
def testBinBuildWithExistingChroot(self):
"""Tests whether the --nosdk option works."""
self._PrepareFull(extra_cmd_args=['--nosdk'])
# Do not force chroot replacement in build config.
self._run._config.chroot_replace = False
self._Run(dir_exists=True)
self.assertCommandContains(['cros_sdk'], expected=False)
class SetupBoardTest(generic_stages_unittest.RunCommandAbstractStageTest):
"""Test building the board"""
def ConstructStage(self):
return build_stages.SetupBoardStage(self._run, self._current_board)
def _RunFull(self, dir_exists=False):
"""Helper for testing a full builder."""
self._Run(dir_exists)
cmd = ['./setup_board', '--board=%s' % self._current_board, '--nousepkg']
self.assertCommandContains(cmd, expected=not dir_exists)
cmd = ['./setup_board', '--skip_chroot_upgrade']
self.assertCommandContains(cmd, expected=False)
def testFullBuildWithProfile(self):
"""Tests whether full builds add profile flag when requested."""
self._PrepareFull(extra_config={'profile': 'foo'})
self._RunFull(dir_exists=False)
self.assertCommandContains(['./setup_board', '--profile=foo'])
def testFullBuildWithOverriddenProfile(self):
"""Tests whether full builds add overridden profile flag when requested."""
self._PrepareFull(extra_cmd_args=['--profile', 'smock'])
self._RunFull(dir_exists=False)
self.assertCommandContains(['./setup_board', '--profile=smock'])
def testFullBuildWithLatestToolchain(self):
"""Tests whether we use --nousepkg for creating the board"""
self._PrepareFull()
self._RunFull(dir_exists=False)
def _RunBin(self, dir_exists):
"""Helper for testing a binary builder."""
self._Run(dir_exists)
self.assertCommandContains(['./setup_board'])
cmd = ['./setup_board', '--nousepkg']
self.assertCommandContains(cmd, expected=self._run.options.latest_toolchain)
cmd = ['./setup_board', '--skip_chroot_upgrade']
self.assertCommandContains(cmd, expected=False)
def testBinBuildWithBoard(self):
"""Tests whether we don't create the board when it's there."""
self._PrepareBin()
self._RunBin(dir_exists=True)
def testBinBuildWithMissingBoard(self):
"""Tests whether we create the board when it's missing."""
self._PrepareBin()
self._RunBin(dir_exists=False)
def testBinBuildWithLatestToolchain(self):
"""Tests whether we use --nousepkg for creating the board."""
self._PrepareBin()
self._RunBin(dir_exists=False)
def testSDKBuild(self):
"""Tests whether we use --skip_chroot_upgrade for SDK builds."""
extra_config = {'build_type': constants.CHROOT_BUILDER_TYPE}
self._PrepareFull(extra_config=extra_config)
self._Run(dir_exists=False)
self.assertCommandContains(['./setup_board', '--skip_chroot_upgrade'])
class UprevStageTest(generic_stages_unittest.AbstractStageTest):
"""Tests for the UprevStage class."""
def setUp(self):
self.mox.StubOutWithMock(commands, 'UprevPackages')
self._Prepare()
def ConstructStage(self):
return build_stages.UprevStage(self._run)
def testBuildRev(self):
"""Uprevving the build without uprevving chrome."""
self._run.config['uprev'] = True
commands.UprevPackages(self.build_root, self._boards, [], enter_chroot=True)
self.mox.ReplayAll()
self.RunStage()
self.mox.VerifyAll()
def testNoRev(self):
"""No paths are enabled."""
self._run.config['uprev'] = False
self.mox.ReplayAll()
self.RunStage()
self.mox.VerifyAll()
class BuildPackagesStageTest(generic_stages_unittest.AbstractStageTest):
"""Tests BuildPackagesStage."""
def setUp(self):
self._release_tag = None
self.StartPatcher(BuilderRunMock())
def ConstructStage(self):
self._run.attrs.release_tag = self._release_tag
return build_stages.BuildPackagesStage(self._run, self._current_board)
@contextlib.contextmanager
def RunStageWithConfig(self):
"""Run the given config"""
try:
with cros_build_lib_unittest.RunCommandMock() as rc:
rc.SetDefaultCmdResult()
with cros_test_lib.OutputCapturer():
with cros_test_lib.LoggingCapturer():
self.RunStage()
yield rc
except AssertionError as ex:
msg = '%s failed the following test:\n%s' % (self._bot_id, ex)
raise AssertionError(msg)
def RunTestsWithBotId(self, bot_id, options_tests=True):
"""Test with the config for the specified bot_id."""
self._Prepare(bot_id)
self._run.options.tests = options_tests
with self.RunStageWithConfig() as rc:
cfg = self._run.config
rc.assertCommandContains(['./build_packages'])
rc.assertCommandContains(['./build_packages', '--skip_chroot_upgrade'])
rc.assertCommandContains(['./build_packages', '--nousepkg'],
expected=not cfg['usepkg_build_packages'])
build_tests = cfg['build_tests'] and self._run.options.tests
rc.assertCommandContains(['./build_packages', '--nowithautotest'],
expected=not build_tests)
def testAllConfigs(self):
"""Test all major configurations"""
task = self.RunTestsWithBotId
with parallel.BackgroundTaskRunner(task) as queue:
# Loop through all major configuration types and pick one from each.
for bot_type in config.CONFIG_TYPE_DUMP_ORDER:
for bot_id in config.config:
if bot_id.endswith(bot_type):
# Skip any config without a board, since those configs do not
# build packages.
cfg = config.config[bot_id]
if cfg.boards:
queue.put([bot_id])
break
def testNoTests(self):
"""Test that self.options.tests = False works."""
self.RunTestsWithBotId('x86-generic-paladin', options_tests=False)
class BuildImageStageMock(partial_mock.PartialMock):
"""Partial mock for BuildImageStage."""
TARGET = 'chromite.cbuildbot.stages.build_stages.BuildImageStage'
ATTRS = ('_BuildImages', '_GenerateAuZip')
def _BuildImages(self, *args, **kwargs):
with patches(
patch(os, 'symlink'),
patch(os, 'readlink', return_value='foo.txt')):
self.backup['_BuildImages'](*args, **kwargs)
def _GenerateAuZip(self, *args, **kwargs):
with patch(git, 'ReinterpretPathForChroot', return_value='/chroot/path'):
self.backup['_GenerateAuZip'](*args, **kwargs)
class BuildImageStageTest(BuildPackagesStageTest):
"""Tests BuildImageStage."""
def setUp(self):
self.StartPatcher(BuildImageStageMock())
def ConstructStage(self):
return build_stages.BuildImageStage(self._run, self._current_board)
def RunTestsWithReleaseConfig(self, release_tag):
self._release_tag = release_tag
with parallel_unittest.ParallelMock():
with self.RunStageWithConfig() as rc:
cfg = self._run.config
cmd = ['./build_image', '--version=%s' % (self._release_tag or '')]
rc.assertCommandContains(cmd, expected=cfg['images'])
rc.assertCommandContains(['./image_to_vm.sh'],
expected=cfg['vm_tests'])
cmd = ['./build_library/generate_au_zip.py', '-o', '/chroot/path']
rc.assertCommandContains(cmd, expected=cfg['images'])
def RunTestsWithBotId(self, bot_id, options_tests=True):
"""Test with the config for the specified bot_id."""
release_tag = '0.0.1'
self._Prepare(bot_id)
self._run.options.tests = options_tests
self._run.attrs.release_tag = release_tag
task = self.RunTestsWithReleaseConfig
steps = [lambda: task(tag) for tag in (None, release_tag)]
parallel.RunParallelSteps(steps)
if __name__ == '__main__':
cros_test_lib.main()