blob: 9d73c65f62487224a4827e3cb5ee0df570c5cb28 [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 json
import os
from chromite.cbuildbot import afdo
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 failures_lib
from chromite.lib import gs
from chromite.lib import osutils
from chromite.lib import portage_util
from chromite.lib.buildstore import FakeBuildStore
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 = portage_util.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 OrderfileUpdateChromeEbuildStageTest(
generic_stages_unittest.AbstractStageTestCase):
"""Test updating Chrome ebuild file with orderfile."""
def setUp(self):
# Intercept the commands.RunBuildScript
self.command = self.PatchObject(commands, 'RunBuildScript', autospec=True)
# Setup temp directory
chroot_tmp = os.path.join(self.build_root, 'chroot', 'tmp')
osutils.SafeMakedirs(chroot_tmp)
self._Prepare()
self.buildstore = FakeBuildStore()
def ConstructStage(self):
return afdo_stages.OrderfileUpdateChromeEbuildStage(
self._run, self.buildstore, self._current_board)
def testRunPass(self):
# Redirect the current tempdir to read/write contents inside it.
self.PatchObject(osutils.TempDir, '__enter__',
return_value=self.tempdir)
input_proto_file = os.path.join(self.tempdir, 'input.json')
output_proto_file = os.path.join(self.tempdir, 'output.json')
self.RunStage()
# Verify the command is called correctly
self.command.assert_called_once_with(
self.build_root,
['build_api',
'chromite.api.ToolchainService/UpdateChromeEbuildWithOrderfile',
'--input-json', input_proto_file,
'--output-json', output_proto_file],
chromite_cmd=True,
redirect_stdout=True
)
# Verify the input proto has all the information
input_proto = json.loads(osutils.ReadFile(input_proto_file))
self.assertEqual(input_proto['build_target']['name'],
self._current_board)
class UploadVettedOrderfileStageTest(
generic_stages_unittest.AbstractStageTestCase):
"""Test updating Chrome ebuild file with orderfile."""
def setUp(self):
# Intercept the commands.RunBuildScript
self.command = self.PatchObject(commands, 'RunBuildScript', autospec=True)
# Setup temp directory
chroot_tmp = os.path.join(self.build_root, 'chroot', 'tmp')
osutils.SafeMakedirs(chroot_tmp)
self._Prepare()
self.buildstore = FakeBuildStore()
def ConstructStage(self):
return afdo_stages.UploadVettedOrderfileStage(
self._run, self.buildstore, self._current_board)
def testRunRaiseException(self):
# Redirect the current tempdir to read/write contents inside it.
self.PatchObject(osutils.TempDir, '__enter__',
return_value=self.tempdir)
output_proto_file = os.path.join(self.tempdir, 'output.json')
# Write fail signal in output proto
with open(output_proto_file, 'w') as f:
output_proto = {
'status': False
}
json.dump(output_proto, f)
with self.assertRaises(failures_lib.StepFailure) as context:
self.RunStage()
self.assertEqual('Failed to upload vetted orderfile',
str(context.exception))
def testRunPass(self):
# Redirect the current tempdir to read/write contents inside it.
self.PatchObject(osutils.TempDir, '__enter__',
return_value=self.tempdir)
input_proto_file = os.path.join(self.tempdir, 'input.json')
output_proto_file = os.path.join(self.tempdir, 'output.json')
# Write pass signal in output proto
with open(output_proto_file, 'w') as f:
output_proto = {
'status': True
}
json.dump(output_proto, f)
self.RunStage()
# Verify the command is called correctly
self.command.assert_called_once_with(
self.build_root,
['build_api',
'chromite.api.ToolchainService/UploadVettedOrderfile',
'--input-json', input_proto_file,
'--output-json', output_proto_file],
chromite_cmd=True,
redirect_stdout=True
)