blob: 712e2614237c1f77ee659f25b7855fa5f30a8b51 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tests for modifying a tryjob."""
import json
import unittest
import unittest.mock as mock
import get_llvm_hash
import modify_a_tryjob
import test_helpers
import update_packages_and_run_tests
import update_tryjob_status
class ModifyATryjobTest(unittest.TestCase):
"""Unittests for modifying a tryjob."""
def testNoTryjobsInStatusFile(self):
bisect_test_contents = {"start": 369410, "end": 369420, "jobs": []}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
revision_to_modify = 369411
args_output = test_helpers.ArgsOutputTest()
args_output.builders = None
args_output.options = None
# Verify the exception is raised there are no tryjobs in the status file
# and the mode is not to 'add' a tryjob.
with self.assertRaises(SystemExit) as err:
modify_a_tryjob.PerformTryjobModification(
revision_to_modify,
modify_a_tryjob.ModifyTryjob.REMOVE,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
self.assertEqual(
str(err.exception), "No tryjobs in %s" % temp_json_file
)
# Simulate the behavior of `FindTryjobIndex()` when the index of the tryjob
# was not found.
@mock.patch.object(
update_tryjob_status, "FindTryjobIndex", return_value=None
)
def testNoTryjobIndexFound(self, mock_find_tryjob_index):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [
{"rev": 369411, "status": "pending", "buildbucket_id": 1200}
],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
revision_to_modify = 369412
args_output = test_helpers.ArgsOutputTest()
args_output.builders = None
args_output.options = None
# Verify the exception is raised when the index of the tryjob was not
# found in the status file and the mode is not to 'add' a tryjob.
with self.assertRaises(ValueError) as err:
modify_a_tryjob.PerformTryjobModification(
revision_to_modify,
modify_a_tryjob.ModifyTryjob.REMOVE,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
self.assertEqual(
str(err.exception),
"Unable to find tryjob for %d in %s"
% (revision_to_modify, temp_json_file),
)
mock_find_tryjob_index.assert_called_once()
# Simulate the behavior of `FindTryjobIndex()` when the index of the tryjob
# was found.
@mock.patch.object(update_tryjob_status, "FindTryjobIndex", return_value=0)
def testSuccessfullyRemovedTryjobInStatusFile(self, mock_find_tryjob_index):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [
{"rev": 369414, "status": "pending", "buildbucket_id": 1200}
],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
revision_to_modify = 369414
args_output = test_helpers.ArgsOutputTest()
args_output.builders = None
args_output.options = None
modify_a_tryjob.PerformTryjobModification(
revision_to_modify,
modify_a_tryjob.ModifyTryjob.REMOVE,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
# Verify that the tryjob was removed from the status file.
with open(temp_json_file) as status_file:
bisect_contents = json.load(status_file)
expected_file_contents = {
"start": 369410,
"end": 369420,
"jobs": [],
}
self.assertDictEqual(bisect_contents, expected_file_contents)
mock_find_tryjob_index.assert_called_once()
# Simulate the behavior of `RunTryJobs()` when successfully submitted a
# tryjob.
@mock.patch.object(update_packages_and_run_tests, "RunTryJobs")
# Simulate the behavior of `FindTryjobIndex()` when the index of the tryjob
# was found.
@mock.patch.object(update_tryjob_status, "FindTryjobIndex", return_value=0)
def testSuccessfullyRelaunchedTryjob(
self, mock_find_tryjob_index, mock_run_tryjob
):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [
{
"rev": 369411,
"status": "bad",
"link": "https://some_tryjob_link.com",
"buildbucket_id": 1200,
"cl": 123,
"extra_cls": None,
"options": None,
"builder": ["some-builder-tryjob"],
}
],
}
tryjob_result = [
{"link": "https://some_new_tryjob_link.com", "buildbucket_id": 20}
]
mock_run_tryjob.return_value = tryjob_result
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
revision_to_modify = 369411
args_output = test_helpers.ArgsOutputTest()
args_output.builders = None
args_output.options = None
modify_a_tryjob.PerformTryjobModification(
revision_to_modify,
modify_a_tryjob.ModifyTryjob.RELAUNCH,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
# Verify that the tryjob's information was updated after submtting the
# tryjob.
with open(temp_json_file) as status_file:
bisect_contents = json.load(status_file)
expected_file_contents = {
"start": 369410,
"end": 369420,
"jobs": [
{
"rev": 369411,
"status": "pending",
"link": "https://some_new_tryjob_link.com",
"buildbucket_id": 20,
"cl": 123,
"extra_cls": None,
"options": None,
"builder": ["some-builder-tryjob"],
}
],
}
self.assertDictEqual(bisect_contents, expected_file_contents)
mock_find_tryjob_index.assert_called_once()
mock_run_tryjob.assert_called_once()
# Simulate the behavior of `FindTryjobIndex()` when the index of the tryjob
# was found.
@mock.patch.object(update_tryjob_status, "FindTryjobIndex", return_value=0)
def testAddingTryjobThatAlreadyExists(self, mock_find_tryjob_index):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [
{"rev": 369411, "status": "bad", "builder": ["some-builder"]}
],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
revision_to_add = 369411
# Index of the tryjob in 'jobs' list.
tryjob_index = 0
args_output = test_helpers.ArgsOutputTest()
args_output.options = None
# Verify the exception is raised when the tryjob that is going to added
# already exists in the status file (found its index).
with self.assertRaises(ValueError) as err:
modify_a_tryjob.PerformTryjobModification(
revision_to_add,
modify_a_tryjob.ModifyTryjob.ADD,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
self.assertEqual(
str(err.exception),
"Tryjob already exists (index is %d) in %s."
% (tryjob_index, temp_json_file),
)
mock_find_tryjob_index.assert_called_once()
# Simulate the behavior of `FindTryjobIndex()` when the tryjob was not found.
@mock.patch.object(
update_tryjob_status, "FindTryjobIndex", return_value=None
)
def testSuccessfullyDidNotAddTryjobOutsideOfBisectionBounds(
self, mock_find_tryjob_index
):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [{"rev": 369411, "status": "bad"}],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
# Add a revision that is outside of 'start' and 'end'.
revision_to_add = 369450
args_output = test_helpers.ArgsOutputTest()
args_output.options = None
# Verify the exception is raised when adding a tryjob that does not exist
# and is not within 'start' and 'end'.
with self.assertRaises(ValueError) as err:
modify_a_tryjob.PerformTryjobModification(
revision_to_add,
modify_a_tryjob.ModifyTryjob.ADD,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
self.assertEqual(
str(err.exception),
"Failed to add tryjob to %s" % temp_json_file,
)
mock_find_tryjob_index.assert_called_once()
# Simulate the behavior of `AddTryjob()` when successfully submitted the
# tryjob and constructed the tryjob information (a dictionary).
@mock.patch.object(modify_a_tryjob, "AddTryjob")
# Simulate the behavior of `GetLLVMHashAndVersionFromSVNOption()` when
# successfully retrieved the git hash of the revision to launch a tryjob for.
@mock.patch.object(
get_llvm_hash,
"GetLLVMHashAndVersionFromSVNOption",
return_value=("a123testhash1", 369418),
)
# Simulate the behavior of `FindTryjobIndex()` when the tryjob was not found.
@mock.patch.object(
update_tryjob_status, "FindTryjobIndex", return_value=None
)
def testSuccessfullyAddedTryjob(
self, mock_find_tryjob_index, mock_get_llvm_hash, mock_add_tryjob
):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [{"rev": 369411, "status": "bad"}],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
# Add a revision that is outside of 'start' and 'end'.
revision_to_add = 369418
args_output = test_helpers.ArgsOutputTest()
args_output.options = None
new_tryjob_info = {
"rev": revision_to_add,
"status": "pending",
"options": args_output.options,
"extra_cls": args_output.extra_change_lists,
"builder": args_output.builders,
}
mock_add_tryjob.return_value = new_tryjob_info
modify_a_tryjob.PerformTryjobModification(
revision_to_add,
modify_a_tryjob.ModifyTryjob.ADD,
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
# Verify that the tryjob was added to the status file.
with open(temp_json_file) as status_file:
bisect_contents = json.load(status_file)
expected_file_contents = {
"start": 369410,
"end": 369420,
"jobs": [{"rev": 369411, "status": "bad"}, new_tryjob_info],
}
self.assertDictEqual(bisect_contents, expected_file_contents)
mock_find_tryjob_index.assert_called_once()
mock_get_llvm_hash.assert_called_once_with(revision_to_add)
mock_add_tryjob.assert_called_once()
# Simulate the behavior of `FindTryjobIndex()` when the tryjob was found.
@mock.patch.object(update_tryjob_status, "FindTryjobIndex", return_value=0)
def testModifyATryjobOptionDoesNotExist(self, mock_find_tryjob_index):
bisect_test_contents = {
"start": 369410,
"end": 369420,
"jobs": [{"rev": 369414, "status": "bad"}],
}
# Create a temporary .JSON file to simulate a .JSON file that has bisection
# contents.
with test_helpers.CreateTemporaryJsonFile() as temp_json_file:
with open(temp_json_file, "w") as f:
test_helpers.WritePrettyJsonFile(bisect_test_contents, f)
# Add a revision that is outside of 'start' and 'end'.
revision_to_modify = 369414
args_output = test_helpers.ArgsOutputTest()
args_output.builders = None
args_output.options = None
# Verify the exception is raised when the modify a tryjob option does not
# exist.
with self.assertRaises(ValueError) as err:
modify_a_tryjob.PerformTryjobModification(
revision_to_modify,
"remove_link",
temp_json_file,
args_output.extra_change_lists,
args_output.options,
args_output.builders,
args_output.chroot_path,
args_output.verbose,
)
self.assertEqual(
str(err.exception),
'Invalid "modify_tryjob" option provided: remove_link',
)
mock_find_tryjob_index.assert_called_once()
if __name__ == "__main__":
unittest.main()