blob: 307573a0ae35a3047a44747fab4177cfa63c3420 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2018 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 updating Chrome ebuild stages."""
from __future__ import print_function
import os
import mock
from chromite.api.gen.chromite.api import toolchain_pb2
from chromite.cbuildbot import afdo
from chromite.cbuildbot import cbuildbot_unittest
from chromite.cbuildbot import commands
from chromite.cbuildbot.stages import afdo_stages
from chromite.cbuildbot.stages import generic_stages_unittest
from chromite.lib import alerts
from chromite.lib import cros_test_lib
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import portage_util
from chromite.lib.buildstore import FakeBuildStore
from chromite.lib.parser import package_info
def _GenerateAFDOGenerateTest(chrome_version_str, expected_to_generate_profile,
test_name):
class Test(generic_stages_unittest.AbstractStageTestCase):
"""Test that we don't update non-r1 AFDO profiles"""
def setUp(self):
self.PatchObject(afdo, 'CanGenerateAFDOData', lambda _: True)
chrome_version = package_info.SplitCPV(chrome_version_str)
self.PatchObject(portage_util, 'PortageqBestVisible',
lambda *_, **_2: chrome_version)
self.wait_for_data = self.PatchObject(
afdo, 'WaitForAFDOPerfData', autospec=True, wraps=lambda *_: True)
afdo_path = '/does/not/exist/afdo.prof'
self.generate_afdo_data = self.PatchObject(
afdo, 'GenerateAFDOData', autospec=True, wraps=lambda *_: afdo_path)
self.PatchObject(afdo_stages.AFDODataGenerateStage, '_GetCurrentArch',
lambda *_: 'some_arch')
self.PatchObject(alerts, 'SendEmailLog')
self._Prepare()
self.buildstore = FakeBuildStore()
def ConstructStage(self):
return afdo_stages.AFDODataGenerateStage(self._run, self.buildstore,
'some_board')
def testAFDOUpdateChromeEbuildStage(self):
self.RunStage()
if expected_to_generate_profile:
self.assertTrue(self.wait_for_data.called)
self.assertTrue(self.generate_afdo_data.called)
else:
self.assertFalse(self.wait_for_data.called)
self.assertFalse(self.generate_afdo_data.called)
Test.__name__ = test_name
return Test
def _MakeChromeVersionWithRev(rev):
return 'chromeos-chrome/chromeos-chrome-68.0.3436.0_rc-r%d' % rev
R1Test = _GenerateAFDOGenerateTest(
chrome_version_str=_MakeChromeVersionWithRev(1),
expected_to_generate_profile=True,
test_name='AFDODataGenerateStageUpdatesR1ProfilesTest',
)
R2Test = _GenerateAFDOGenerateTest(
chrome_version_str=_MakeChromeVersionWithRev(2),
expected_to_generate_profile=False,
test_name='AFDODataGenerateStageDoesntUpdateNonR1ProfilesTest',
)
class UpdateChromeEbuildTest(generic_stages_unittest.AbstractStageTestCase):
"""Test updating Chrome ebuild files"""
def setUp(self):
# Intercept afdo.UpdateChromeEbuildAFDOFile so that we can check how it is
# called.
self.patch_mock = self.PatchObject(
afdo, 'UpdateChromeEbuildAFDOFile', autospec=True)
# Don't care the return value of portage_util.PortageqBestVisible
self.PatchObject(portage_util, 'PortageqBestVisible')
# Don't care the return value of gs.GSContext
self.PatchObject(gs, 'GSContext')
# Don't call the getters; Use mock responses instead.
self.PatchDict(
afdo.PROFILE_SOURCES, {
'benchmark': lambda *_: 'benchmark.afdo',
'silvermont': lambda *_: 'silvermont.afdo'
},
clear=True)
self._Prepare()
self.buildstore = FakeBuildStore()
def ConstructStage(self):
return afdo_stages.AFDOUpdateChromeEbuildStage(self._run, self.buildstore)
def testAFDOUpdateChromeEbuildStage(self):
self.RunStage()
# afdo.UpdateChromeEbuildAFDOFile should be called with the mock responses
# from profile source specific query.
self.patch_mock.assert_called_with('amd64-generic', {
'benchmark': 'benchmark.afdo',
'silvermont': 'silvermont.afdo'
})
class GenerateAFDOArtifactStageTests(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase):
"""Test class of GenerateAFDOArtifactStage."""
RELEASE_TAG = ''
# pylint: disable=protected-access
def setUp(self):
self._Prepare()
self.rc_mock = self.StartPatcher(cros_test_lib.RunCommandMock())
self.rc_mock.SetDefaultCmdResult()
self.buildstore = FakeBuildStore()
# Prepare the directories
chroot_tmp = os.path.join(self.build_root, 'chroot', 'tmp')
osutils.SafeMakedirs(chroot_tmp)
# pylint: disable=arguments-differ
def ConstructStage(self, is_afdo):
self._run.GetArchive().SetupArchivePath()
if is_afdo:
return afdo_stages.GenerateBenchmarkAFDOStage(
self._run, self.buildstore, self._current_board)
return afdo_stages.GenerateChromeOrderfileStage(
self._run, self.buildstore, self._current_board)
def testRunSuccess(self):
"""Test the main function runs without problems."""
for is_afdo in [True, False]:
stage = self.ConstructStage(is_afdo)
artifacts = ['tarball.1.xz', '/path/to/tarball.2.xz']
self.PatchObject(stage, 'ArtifactUploader')
mock_generate = self.PatchObject(
commands, 'GenerateAFDOArtifacts',
return_value=artifacts)
mock_put = self.PatchObject(stage._upload_queue, 'put')
stage.PerformStage()
output_path = os.path.abspath(
os.path.join(self.build_root, 'chroot',
stage.archive_path))
if is_afdo:
target = toolchain_pb2.BENCHMARK_AFDO
else:
target = toolchain_pb2.ORDERFILE
mock_generate.assert_called_once_with(
self.build_root, None, self._current_board,
output_path, target)
calls = [mock.call([os.path.basename(x)]) for x in artifacts]
mock_put.assert_has_calls(calls)
class VerifyAFDOArtifactStageTests(
generic_stages_unittest.AbstractStageTestCase,
cbuildbot_unittest.SimpleBuilderTestCase):
"""Test class of VerifyAFDOArtifactStage."""
RELEASE_TAG = ''
# pylint: disable=protected-access
def setUp(self):
self._Prepare()
self.rc_mock = self.StartPatcher(cros_test_lib.RunCommandMock())
self.rc_mock.SetDefaultCmdResult()
self.buildstore = FakeBuildStore()
# pylint: disable=arguments-differ
def ConstructStage(self, artifact_type, stage_type):
self._run.GetArchive().SetupArchivePath()
if artifact_type == 'orderfile':
if stage_type == 'update':
return afdo_stages.OrderfileUpdateChromeEbuildStage(
self._run, self.buildstore, self._current_board)
return afdo_stages.UploadVettedOrderfileStage(
self._run, self.buildstore, self._current_board)
if artifact_type == 'kernel_afdo':
if stage_type == 'update':
return afdo_stages.KernelAFDOUpdateEbuildStage(
self._run, self.buildstore, self._current_board)
return afdo_stages.UploadVettedKernelAFDOStage(
self._run, self.buildstore, self._current_board)
if stage_type == 'update':
return afdo_stages.ChromeAFDOUpdateEbuildStage(
self._run, self.buildstore, self._current_board)
return afdo_stages.UploadVettedChromeAFDOStage(
self._run, self.buildstore, self._current_board)
def testOrderfileUpdateSuccess(
self, artifact_type='orderfile', stage_type='update'):
"""Test update ebuild with orderfile call correctly.
Parameterize the two arguments for testing different stage types.
"""
stage = self.ConstructStage(artifact_type, stage_type)
mock_verify = self.PatchObject(
commands, 'VerifyAFDOArtifacts', return_value=True)
stage.PerformStage()
# Verify wrapper function is called correctly.
if artifact_type == 'orderfile':
target = toolchain_pb2.ORDERFILE
elif artifact_type == 'kernel_afdo':
target = toolchain_pb2.KERNEL_AFDO
else:
target = toolchain_pb2.CHROME_AFDO
if stage_type == 'update':
build_api = 'chromite.api.ToolchainService/UpdateEbuildWithAFDOArtifacts'
else:
build_api = 'chromite.api.ToolchainService/UploadVettedAFDOArtifacts'
mock_verify.assert_called_once_with(
self.build_root, self._current_board,
target, build_api)
def testOrderfileUploadSuccess(self):
"""Test upload vetted orderfile call correctly."""
self.testOrderfileUpdateSuccess(stage_type='upload')
def testKernelAFDOUpdateSuccess(self):
"""Test update ebuild with kernel AFDO call correctly."""
self.testOrderfileUpdateSuccess(artifact_type='kernel_afdo')
def testKernelAFDOUploadSuccess(self):
"""Test upload vetted kernel AFDO call correctly."""
self.testOrderfileUpdateSuccess(artifact_type='kernel_afdo',
stage_type='upload')
def testChromeAFDOUpdateSuccess(self):
"""Test update ebuild with Chrome AFDO call correctly."""
self.testOrderfileUpdateSuccess(artifact_type='chrome_afdo')
def testChromeAFDOUploadSuccess(self):
"""Test upload vetted Chrome AFDO call correctly."""
self.testOrderfileUpdateSuccess(artifact_type='chrome_afdo',
stage_type='upload')