blob: d852893a8e3874adc7215357beddcf74e0323a7e [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 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.
"""Unittests for running tests after updating packages."""
from __future__ import print_function
import json
import subprocess
import unittest
import unittest.mock as mock
import chroot
import get_llvm_hash
import git
import test_helpers
import update_chromeos_llvm_hash
import update_packages_and_run_tests
# Testing with tryjobs.
class UpdatePackagesAndRunTryjobsTest(unittest.TestCase):
"""Unittests when running tryjobs after updating packages."""
def testNoLastTestedFile(self):
self.assertEqual(
update_packages_and_run_tests.UnchangedSinceLastRun(None, {}), False)
def testEmptyLastTestedFile(self):
with test_helpers.CreateTemporaryFile() as temp_file:
self.assertEqual(
update_packages_and_run_tests.UnchangedSinceLastRun(temp_file, {}),
False)
def testLastTestedFileDoesNotExist(self):
# Simulate 'open()' on a lasted tested file that does not exist.
mock.mock_open(read_data='')
self.assertEqual(
update_packages_and_run_tests.UnchangedSinceLastRun(
'/some/file/that/does/not/exist.txt', {}), False)
def testMatchedLastTestedFile(self):
with test_helpers.CreateTemporaryFile() as last_tested_file:
arg_dict = {
'svn_version':
1234,
'ebuilds': [
'/path/to/package1-r2.ebuild',
'/path/to/package2/package2-r3.ebuild'
],
'builders': [
'kevin-llvm-next-toolchain-tryjob',
'eve-llvm-next-toolchain-tryjob'
],
'extra_cls': [10, 1],
'tryjob_options': ['latest-toolchain', 'hwtest']
}
with open(last_tested_file, 'w') as f:
f.write(json.dumps(arg_dict, indent=2))
self.assertEqual(
update_packages_and_run_tests.UnchangedSinceLastRun(
last_tested_file, arg_dict), True)
def testGetTryJobCommandWithNoExtraInformation(self):
change_list = 1234
builder = 'nocturne'
expected_cmd = [
'cros', 'tryjob', '--yes', '--json', '-g',
'%d' % change_list, builder
]
self.assertEqual(
update_packages_and_run_tests.GetTryJobCommand(change_list, None, None,
builder), expected_cmd)
def testGetTryJobCommandWithExtraInformation(self):
change_list = 4321
extra_cls = [1000, 10]
options = ['option1', 'option2']
builder = 'kevin'
expected_cmd = [
'cros',
'tryjob',
'--yes',
'--json',
'-g',
'%d' % change_list,
'-g',
'%d' % extra_cls[0],
'-g',
'%d' % extra_cls[1],
'--%s' % options[0],
'--%s' % options[1],
builder,
]
self.assertEqual(
update_packages_and_run_tests.GetTryJobCommand(
change_list, extra_cls, options, builder), expected_cmd)
@mock.patch.object(
update_packages_and_run_tests,
'GetCurrentTimeInUTC',
return_value='2019-09-09')
@mock.patch.object(update_packages_and_run_tests, 'AddLinksToCL')
@mock.patch.object(subprocess, 'check_output')
def testSuccessfullySubmittedTryJob(self, mock_cmd, mock_add_links_to_cl,
mock_launch_time):
expected_cmd = [
'cros', 'tryjob', '--yes', '--json', '-g',
'%d' % 900, '-g',
'%d' % 1200, '--some_option', 'builder1'
]
bb_id = '1234'
url = 'https://some_tryjob_url.com'
mock_cmd.return_value = json.dumps([{'buildbucket_id': bb_id, 'url': url}])
chroot_path = '/some/path/to/chroot'
cl = 900
extra_cls = [1200]
options = ['some_option']
builders = ['builder1']
tests = update_packages_and_run_tests.RunTryJobs(cl, extra_cls, options,
builders, chroot_path)
expected_tests = [{
'launch_time': mock_launch_time.return_value,
'link': url,
'buildbucket_id': int(bb_id),
'extra_cls': extra_cls,
'options': options,
'builder': builders
}]
self.assertEqual(tests, expected_tests)
mock_cmd.assert_called_once_with(
expected_cmd, cwd=chroot_path, encoding='utf-8')
mock_add_links_to_cl.assert_called_once()
@mock.patch.object(update_packages_and_run_tests, 'AddLinksToCL')
@mock.patch.object(subprocess, 'check_output')
def testSuccessfullySubmittedRecipeBuilders(self, mock_cmd,
mock_add_links_to_cl):
expected_cmd = [
'bb', 'add', '-json', '-cl',
'crrev.com/c/%s' % 900, '-cl',
'crrev.com/c/%s' % 1200, 'some_option', 'builder1'
]
bb_id = '1234'
create_time = '2020-04-18T00:03:53.978767Z'
mock_cmd.return_value = json.dumps({'id': bb_id, 'createTime': create_time})
chroot_path = '/some/path/to/chroot'
cl = 900
extra_cls = [1200]
options = ['some_option']
builders = ['builder1']
tests = update_packages_and_run_tests.StartRecipeBuilders(
cl, extra_cls, options, builders, chroot_path)
expected_tests = [{
'launch_time': create_time,
'link': 'http://ci.chromium.org/b/%s' % bb_id,
'buildbucket_id': bb_id,
'extra_cls': extra_cls,
'options': options,
'builder': builders
}]
self.assertEqual(tests, expected_tests)
mock_cmd.assert_called_once_with(
expected_cmd, cwd=chroot_path, encoding='utf-8')
mock_add_links_to_cl.assert_called_once()
@mock.patch.object(subprocess, 'check_output', return_value=None)
def testSuccessfullyAddedTestLinkToCL(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
test_cl_number = 1000
tests = [{'link': 'https://some_tryjob_link.com'}]
update_packages_and_run_tests.AddLinksToCL(tests, test_cl_number,
chroot_path)
expected_gerrit_message = [
'%s/chromite/bin/gerrit' % chroot_path, 'message',
str(test_cl_number),
'Started the following tests:\n%s' % tests[0]['link']
]
mock_exec_cmd.assert_called_once_with(expected_gerrit_message)
@mock.patch.object(update_packages_and_run_tests, 'RunTryJobs')
@mock.patch.object(update_chromeos_llvm_hash, 'UpdatePackages')
@mock.patch.object(update_packages_and_run_tests, 'GetCommandLineArgs')
@mock.patch.object(get_llvm_hash, 'GetLLVMHashAndVersionFromSVNOption')
@mock.patch.object(chroot, 'VerifyOutsideChroot', return_value=True)
@mock.patch.object(chroot, 'GetChrootEbuildPaths')
def testUpdatedLastTestedFileWithNewTestedRevision(
self, mock_get_chroot_build_paths, mock_outside_chroot,
mock_get_hash_and_version, mock_get_commandline_args,
mock_update_packages, mock_run_tryjobs):
# Create a temporary file to simulate the last tested file that contains a
# revision.
with test_helpers.CreateTemporaryFile() as last_tested_file:
builders = [
'kevin-llvm-next-toolchain-tryjob', 'eve-llvm-next-toolchain-tryjob'
]
extra_cls = [10, 1]
tryjob_options = ['latest-toolchain', 'hwtest']
ebuilds = [
'/path/to/package1/package1-r2.ebuild',
'/path/to/package2/package2-r3.ebuild'
]
arg_dict = {
'svn_version': 100,
'ebuilds': ebuilds,
'builders': builders,
'extra_cls': extra_cls,
'tryjob_options': tryjob_options
}
# Parepared last tested file
with open(last_tested_file, 'w') as f:
json.dump(arg_dict, f, indent=2)
# Call with a changed LLVM svn version
args_output = test_helpers.ArgsOutputTest()
args_output.is_llvm_next = True
args_output.extra_change_lists = extra_cls
args_output.last_tested = last_tested_file
args_output.reviewers = []
args_output.subparser_name = 'tryjobs'
args_output.builders = builders
args_output.options = tryjob_options
mock_get_commandline_args.return_value = args_output
mock_get_chroot_build_paths.return_value = ebuilds
mock_get_hash_and_version.return_value = ('a123testhash2', 200)
mock_update_packages.return_value = git.CommitContents(
url='https://some_cl_url.com', cl_number=12345)
mock_run_tryjobs.return_value = [{
'link': 'https://some_tryjob_url.com',
'buildbucket_id': 1234
}]
update_packages_and_run_tests.main()
# Verify that the lasted tested file has been updated to the new LLVM
# revision.
with open(last_tested_file) as f:
arg_dict = json.load(f)
self.assertEqual(arg_dict['svn_version'], 200)
mock_outside_chroot.assert_called_once()
mock_get_commandline_args.assert_called_once()
mock_get_hash_and_version.assert_called_once()
mock_run_tryjobs.assert_called_once()
mock_update_packages.assert_called_once()
class UpdatePackagesAndRunTestCQTest(unittest.TestCase):
"""Unittests for CQ dry run after updating packages."""
def testGetCQDependString(self):
test_no_changelists = []
test_single_changelist = [1234]
test_multiple_changelists = [1234, 5678]
self.assertIsNone(
update_packages_and_run_tests.GetCQDependString(test_no_changelists))
self.assertEqual(
update_packages_and_run_tests.GetCQDependString(test_single_changelist),
'\nCq-Depend: chromium:1234')
self.assertEqual(
update_packages_and_run_tests.GetCQDependString(
test_multiple_changelists),
'\nCq-Depend: chromium:1234, chromium:5678')
def testGetCQIncludeTrybotsString(self):
test_no_trybot = None
test_valid_trybot = 'llvm-next'
test_invalid_trybot = 'invalid-name'
self.assertIsNone(
update_packages_and_run_tests.GetCQIncludeTrybotsString(test_no_trybot))
self.assertEqual(
update_packages_and_run_tests.GetCQIncludeTrybotsString(
test_valid_trybot),
'\nCq-Include-Trybots:chromeos/cq:cq-llvm-next-orchestrator')
with self.assertRaises(ValueError) as context:
update_packages_and_run_tests.GetCQIncludeTrybotsString(
test_invalid_trybot)
self.assertIn('is not a valid llvm trybot', str(context.exception))
@mock.patch.object(subprocess, 'check_output', return_value=None)
def testStartCQDryRunNoDeps(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
test_cl_number = 1000
# test with no deps cls.
extra_cls = []
update_packages_and_run_tests.StartCQDryRun(test_cl_number, extra_cls,
chroot_path)
expected_gerrit_message = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(test_cl_number), '1'
]
mock_exec_cmd.assert_called_once_with(expected_gerrit_message)
# Mock ExecCommandAndCaptureOutput for the gerrit command execution.
@mock.patch.object(subprocess, 'check_output', return_value=None)
# test with a single deps cl.
def testStartCQDryRunSingleDep(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
test_cl_number = 1000
extra_cls = [2000]
update_packages_and_run_tests.StartCQDryRun(test_cl_number, extra_cls,
chroot_path)
expected_gerrit_cmd_1 = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(test_cl_number), '1'
]
expected_gerrit_cmd_2 = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(2000), '1'
]
self.assertEqual(mock_exec_cmd.call_count, 2)
self.assertEqual(mock_exec_cmd.call_args_list[0],
mock.call(expected_gerrit_cmd_1))
self.assertEqual(mock_exec_cmd.call_args_list[1],
mock.call(expected_gerrit_cmd_2))
# Mock ExecCommandAndCaptureOutput for the gerrit command execution.
@mock.patch.object(subprocess, 'check_output', return_value=None)
def testStartCQDryRunMultipleDep(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
test_cl_number = 1000
# test with multiple deps cls.
extra_cls = [3000, 4000]
update_packages_and_run_tests.StartCQDryRun(test_cl_number, extra_cls,
chroot_path)
expected_gerrit_cmd_1 = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(test_cl_number), '1'
]
expected_gerrit_cmd_2 = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(3000), '1'
]
expected_gerrit_cmd_3 = [
'%s/chromite/bin/gerrit' % chroot_path, 'label-cq',
str(4000), '1'
]
self.assertEqual(mock_exec_cmd.call_count, 3)
self.assertEqual(mock_exec_cmd.call_args_list[0],
mock.call(expected_gerrit_cmd_1))
self.assertEqual(mock_exec_cmd.call_args_list[1],
mock.call(expected_gerrit_cmd_2))
self.assertEqual(mock_exec_cmd.call_args_list[2],
mock.call(expected_gerrit_cmd_3))
# Mock ExecCommandAndCaptureOutput for the gerrit command execution.
@mock.patch.object(subprocess, 'check_output', return_value=None)
# test with no reviewers.
def testAddReviewersNone(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
reviewers = []
test_cl_number = 1000
update_packages_and_run_tests.AddReviewers(test_cl_number, reviewers,
chroot_path)
self.assertTrue(mock_exec_cmd.not_called)
# Mock ExecCommandAndCaptureOutput for the gerrit command execution.
@mock.patch.object(subprocess, 'check_output', return_value=None)
# test with multiple reviewers.
def testAddReviewersMultiple(self, mock_exec_cmd):
chroot_path = '/abs/path/to/chroot'
reviewers = ['none1@chromium.org', 'none2@chromium.org']
test_cl_number = 1000
update_packages_and_run_tests.AddReviewers(test_cl_number, reviewers,
chroot_path)
expected_gerrit_cmd_1 = [
'%s/chromite/bin/gerrit' % chroot_path, 'reviewers',
str(test_cl_number), 'none1@chromium.org'
]
expected_gerrit_cmd_2 = [
'%s/chromite/bin/gerrit' % chroot_path, 'reviewers',
str(test_cl_number), 'none2@chromium.org'
]
self.assertEqual(mock_exec_cmd.call_count, 2)
self.assertEqual(mock_exec_cmd.call_args_list[0],
mock.call(expected_gerrit_cmd_1))
self.assertEqual(mock_exec_cmd.call_args_list[1],
mock.call(expected_gerrit_cmd_2))
if __name__ == '__main__':
unittest.main()