| # Copyright 2017 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. |
| |
| """Test simple_chrome_builder module.""" |
| |
| import os |
| from unittest import mock |
| |
| from chromite.cbuildbot import commands |
| from chromite.cros_bisect import simple_chrome_builder |
| from chromite.lib import commandline |
| from chromite.lib import cros_logging as logging |
| from chromite.lib import cros_test_lib |
| from chromite.lib import gclient |
| from chromite.lib import git |
| from chromite.lib import osutils |
| |
| |
| class TestSimpleChromeBuilder(cros_test_lib.MockTempDirTestCase): |
| """Tests AutotestEvaluator class.""" |
| BOARD = 'samus' |
| DUT_IP = '192.168.1.1' |
| DUT = commandline.DeviceParser(commandline.DEVICE_SCHEME_SSH)(DUT_IP) |
| |
| def setUp(self): |
| self.default_chromium_dir = os.path.join(self.tempdir, 'chromium') |
| self.default_repo_dir = os.path.join(self.tempdir, 'chromium', 'src') |
| self.default_archive_base = os.path.join(self.tempdir, 'build') |
| self.gclient_path = os.path.join(self.tempdir, 'gclient') |
| self.log_output_args = {'log_output': True} |
| |
| # The SimpleChromeBuilder class sets a 'verbose' setting based on the |
| # ambient logging level, so we must set the logger to the default setting |
| # of INFO for this test and then restore the logger to whatever it was |
| # originally set to when we clean the test up. |
| logger = logging.getLogger() |
| self._prev_logging_level = logger.getEffectiveLevel() |
| logger.setLevel(logging.INFO) |
| |
| def tearDown(self): |
| logger = logging.getLogger() |
| logger.setLevel(self._prev_logging_level) |
| |
| def GetBuilder(self, base_dir=None, board=None, reuse_repo=True, |
| chromium_dir=None, build_dir=None, archive_build=True, |
| reuse_build=True): |
| """Obtains a SimpleChromeBuilder instance. |
| |
| Args: |
| base_dir: Base directory. Default self.tempdir. |
| board: Board name. Default self.BOARD. |
| reuse_repo: True to reuse repo. |
| chromium_dir: Optional. If specified, use the chromium repo the path |
| points to. |
| build_dir: Optional. Store build result to it if specified. |
| archive_build: True to archive build. |
| reuse_build: True to reuse previous build. |
| |
| Returns: |
| A SimpleChromeBuilder instance. |
| """ |
| if base_dir is None: |
| base_dir = self.tempdir |
| if board is None: |
| board = self.BOARD |
| options = cros_test_lib.EasyAttr( |
| base_dir=base_dir, board=board, reuse_repo=reuse_repo, |
| chromium_dir=chromium_dir, build_dir=build_dir, |
| archive_build=archive_build, reuse_build=reuse_build) |
| builder = simple_chrome_builder.SimpleChromeBuilder(options) |
| |
| # Override gclient path. |
| builder.gclient = self.gclient_path |
| |
| return builder |
| |
| def testInit(self): |
| builder = self.GetBuilder() |
| base_dir = self.tempdir |
| self.assertEqual(base_dir, builder.base_dir) |
| self.assertEqual(self.default_chromium_dir, builder.chromium_dir) |
| self.assertEqual(self.default_repo_dir, builder.repo_dir) |
| self.assertTrue(builder.reuse_repo) |
| self.assertTrue(builder.reuse_build) |
| self.assertTrue(builder.archive_build) |
| self.assertEqual(self.default_archive_base, builder.archive_base) |
| self.assertTrue(os.path.isdir(builder.archive_base)) |
| self.assertDictEqual(self.log_output_args, builder.log_output_args) |
| |
| def testInitMissingRequiredArgs(self): |
| options = cros_test_lib.EasyAttr() |
| with self.assertRaises(Exception) as cm: |
| simple_chrome_builder.SimpleChromeBuilder(options) |
| exception_message = str(cm.exception) |
| self.assertIn('Missing command line', exception_message) |
| self.assertIn('SimpleChromeBuilder', exception_message) |
| for arg in simple_chrome_builder.SimpleChromeBuilder.REQUIRED_ARGS: |
| self.assertIn(arg, exception_message) |
| |
| def testInitCustomizedDir(self): |
| base_dir = self.tempdir |
| chromium_dir = os.path.join(base_dir, 'another_chromium') |
| build_dir = os.path.join(base_dir, 'another_build') |
| builder = self.GetBuilder(chromium_dir=chromium_dir, build_dir=build_dir) |
| |
| self.assertEqual(base_dir, builder.base_dir) |
| self.assertEqual(chromium_dir, builder.chromium_dir) |
| self.assertEqual(os.path.join(chromium_dir, 'src'), builder.repo_dir) |
| self.assertTrue(builder.reuse_repo) |
| self.assertTrue(builder.reuse_build) |
| self.assertTrue(builder.archive_build) |
| self.assertEqual(build_dir, builder.archive_base) |
| self.assertTrue(os.path.isdir(builder.archive_base)) |
| self.assertDictEqual(self.log_output_args, builder.log_output_args) |
| |
| def testInitFlipFlags(self): |
| builder = self.GetBuilder(reuse_repo=False, archive_build=False, |
| reuse_build=False) |
| base_dir = self.tempdir |
| self.assertEqual(base_dir, builder.base_dir) |
| self.assertEqual(self.default_chromium_dir, builder.chromium_dir) |
| self.assertEqual(self.default_repo_dir, builder.repo_dir) |
| self.assertFalse(builder.reuse_repo) |
| self.assertFalse(builder.reuse_build) |
| self.assertFalse(builder.archive_build) |
| self.assertEqual(self.default_archive_base, builder.archive_base) |
| self.assertFalse(os.path.isdir(builder.archive_base)) |
| self.assertDictEqual(self.log_output_args, builder.log_output_args) |
| |
| def testSetUp(self): |
| command_mock = self.StartPatcher(cros_test_lib.RunCommandMock()) |
| command_mock.AddCmdResult(['fetch', '--nohooks', 'chromium']) |
| write_config_mock = self.PatchObject(gclient, 'WriteConfigFile') |
| git_mock = self.PatchObject(git, 'RunGit') |
| gsync_mock = self.PatchObject(gclient, 'Sync') |
| |
| builder = self.GetBuilder() |
| builder.SetUp() |
| |
| write_config_mock.assert_called_with( |
| self.gclient_path, self.default_chromium_dir, True, None, managed=False) |
| git_mock.assert_called_with(self.default_repo_dir, |
| ['pull', 'origin', 'master']) |
| gsync_mock.assert_called_with( |
| self.gclient_path, self.default_chromium_dir, reset=True, nohooks=True, |
| verbose=False, run_args=self.log_output_args) |
| |
| def testSetUpSkip(self): |
| write_config_mock = self.PatchObject(gclient, 'WriteConfigFile') |
| git_mock = self.PatchObject(git, 'RunGit') |
| gsync_mock = self.PatchObject(gclient, 'Sync') |
| |
| # Make it looks like a git repo. |
| osutils.SafeMakedirs(os.path.join(self.default_repo_dir, '.git')) |
| |
| builder = self.GetBuilder() |
| builder.SetUp() |
| |
| write_config_mock.assert_not_called() |
| git_mock.assert_not_called() |
| gsync_mock.assert_not_called() |
| |
| def testSetUpExistingRepoException(self): |
| write_config_mock = self.PatchObject(gclient, 'WriteConfigFile') |
| git_mock = self.PatchObject(git, 'RunGit') |
| gsync_mock = self.PatchObject(gclient, 'Sync') |
| |
| # Make it looks like a git repo. |
| osutils.SafeMakedirs(os.path.join(self.default_repo_dir, '.git')) |
| |
| builder = self.GetBuilder(reuse_repo=False) |
| self.assertRaisesRegex(Exception, 'Chromium repo exists.*', |
| builder.SetUp) |
| |
| write_config_mock.assert_not_called() |
| git_mock.assert_not_called() |
| gsync_mock.assert_not_called() |
| |
| def testSyncToHead(self): |
| git_mock = self.PatchObject(git, 'CleanAndCheckoutUpstream') |
| builder = self.GetBuilder() |
| builder.SyncToHead() |
| git_mock.assert_called_with(self.default_repo_dir) |
| |
| def testGclientSync(self): |
| gsync_mock = self.PatchObject(gclient, 'Sync') |
| |
| builder = self.GetBuilder() |
| builder.GclientSync() |
| gsync_mock.assert_called_with( |
| self.gclient_path, self.default_chromium_dir, reset=False, |
| nohooks=False, verbose=False, run_args=self.log_output_args) |
| |
| builder.GclientSync(reset=True, nohooks=True) |
| gsync_mock.assert_called_with( |
| self.gclient_path, self.default_chromium_dir, reset=True, |
| nohooks=True, verbose=False, run_args=self.log_output_args) |
| |
| def testBuildReuse(self): |
| commit_label = 'test' |
| |
| # Let the build already be in archive. |
| archive_path = os.path.join( |
| self.default_archive_base, 'out_%s_%s' % (self.BOARD, commit_label), |
| 'Release') |
| osutils.SafeMakedirs(archive_path) |
| |
| builder = self.GetBuilder() |
| build_to_deploy = builder.Build(commit_label) |
| self.assertEqual(archive_path, build_to_deploy) |
| |
| def _ChromeSdkRunSideEffect(self, *args, **unused_kwargs): |
| if args and len(args[0]) == 3: |
| bash_command = args[0][2] |
| if 'gn gen' in bash_command: |
| build_dir = bash_command.split()[2] |
| osutils.SafeMakedirs(os.path.join(self.default_repo_dir, build_dir)) |
| return mock.DEFAULT |
| |
| def testBuild(self): |
| gsync_mock = self.PatchObject(simple_chrome_builder.SimpleChromeBuilder, |
| 'GclientSync') |
| success_result = cros_test_lib.EasyAttr(returncode=0) |
| chrome_sdk_run_mock = self.PatchObject( |
| commands.ChromeSDK, 'Run', side_effect=self._ChromeSdkRunSideEffect, |
| return_value=success_result) |
| chrome_sdk_ninja_mock = self.PatchObject( |
| commands.ChromeSDK, 'Ninja', return_value=success_result) |
| |
| commit_label = 'test' |
| archive_path = os.path.join( |
| self.default_archive_base, 'out_%s_%s' % (self.BOARD, commit_label), |
| 'Release') |
| |
| self.assertFalse(os.path.isdir(archive_path)) |
| builder = self.GetBuilder() |
| build_to_deploy = builder.Build(commit_label) |
| self.assertEqual(archive_path, build_to_deploy) |
| # Check that build_to_deploy exists after builder.Build() |
| self.assertTrue(os.path.isdir(archive_path)) |
| gsync_mock.assert_called() |
| chrome_sdk_run_mock.assert_called_with( |
| ['bash', '-c', 'gn gen out_%s/Release --args="$GN_ARGS"' % self.BOARD], |
| run_args=self.log_output_args) |
| chrome_sdk_ninja_mock.assert_called_with(run_args=self.log_output_args) |
| |
| def testBuildNoArchive(self): |
| gsync_mock = self.PatchObject(simple_chrome_builder.SimpleChromeBuilder, |
| 'GclientSync') |
| success_result = cros_test_lib.EasyAttr(returncode=0) |
| chrome_sdk_run_mock = self.PatchObject( |
| commands.ChromeSDK, 'Run', side_effect=self._ChromeSdkRunSideEffect, |
| return_value=success_result) |
| chrome_sdk_ninja_mock = self.PatchObject( |
| commands.ChromeSDK, 'Ninja', return_value=success_result) |
| |
| commit_label = 'test' |
| archive_path = os.path.join( |
| self.default_archive_base, 'out_%s_%s' % (self.BOARD, commit_label), |
| 'Release') |
| |
| self.assertFalse(os.path.isdir(archive_path)) |
| builder = self.GetBuilder(archive_build=False) |
| build_to_deploy = builder.Build(commit_label) |
| # No archive. Check that archive_path is not created. |
| self.assertNotEqual(archive_path, build_to_deploy) |
| self.assertFalse(os.path.isdir(archive_path)) |
| |
| self.assertEqual(os.path.join('out_%s' % self.BOARD, 'Release'), |
| build_to_deploy) |
| self.assertTrue(os.path.isdir( |
| os.path.join(self.default_repo_dir, build_to_deploy))) |
| gsync_mock.assert_called() |
| chrome_sdk_run_mock.assert_called_with( |
| ['bash', '-c', 'gn gen out_%s/Release --args="$GN_ARGS"' % self.BOARD], |
| run_args=self.log_output_args) |
| chrome_sdk_ninja_mock.assert_called_with(run_args=self.log_output_args) |
| |
| def testDeploy(self): |
| chrome_sdk_run_mock = self.PatchObject(commands.ChromeSDK, 'Run') |
| build_to_deploy = os.path.join('out_%s' % self.BOARD, 'Release') |
| commit_label = 'test' |
| |
| builder = self.GetBuilder() |
| builder.Deploy(self.DUT, build_to_deploy, commit_label) |
| chrome_sdk_run_mock.assert_called_with( |
| ['deploy_chrome', '--build-dir', build_to_deploy, '--force', |
| '--device', self.DUT_IP], |
| run_args=self.log_output_args) |
| |
| def testDeployWithPort(self): |
| port = '9999' |
| dut = commandline.DeviceParser(commandline.DEVICE_SCHEME_SSH)( |
| self.DUT_IP + ':' + port) |
| chrome_sdk_run_mock = self.PatchObject(commands.ChromeSDK, 'Run') |
| build_to_deploy = os.path.join('out_%s' % self.BOARD, 'Release') |
| commit_label = 'test' |
| |
| builder = self.GetBuilder() |
| builder.Deploy(dut, build_to_deploy, commit_label) |
| chrome_sdk_run_mock.assert_called_with( |
| ['deploy_chrome', '--build-dir', build_to_deploy, '--force', |
| '--device', self.DUT_IP + ':' + port], |
| run_args=self.log_output_args) |