blob: 2cbc281db96e954186c34bfa1800d1db0cdb9f35 [file] [log] [blame]
# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for buildbucket_v2."""
from datetime import date
from datetime import datetime
from typing import Any
from chromite.third_party.google.protobuf import field_mask_pb2
from chromite.third_party.google.protobuf.struct_pb2 import Struct, Value
from chromite.third_party.google.protobuf.timestamp_pb2 import Timestamp
from chromite.third_party.infra_libs.buildbucket.proto import (
build_pb2,
builder_common_pb2,
builds_service_pb2,
common_pb2,
step_pb2,
)
from chromite.cbuildbot import cbuildbot_alerts
from chromite.lib import buildbucket_v2
from chromite.lib import constants
from chromite.lib import cros_test_lib
from chromite.lib import metadata_lib
from chromite.lib.luci.prpc.client import Client
from chromite.lib.luci.prpc.client import new_request
from chromite.lib.luci.prpc.client import ProtocolError
SUCCESS_BUILD = {
"infra": {
"swarming": {
"botDimensions": [
{"key": "cores", "value": "32"},
{"key": "cpu", "value": "x86"},
{"key": "cpu", "value": "x86-64"},
{"key": "cpu", "value": "x86-64-Haswell_GCE"},
{"key": "cpu", "value": "x86-64-avx2"},
{"key": "gce", "value": "1"},
{"key": "gcp", "value": "chromeos-bot"},
{"key": "id", "value": "chromeos-ci-test-bot"},
{
"key": "image",
"value": "chromeos-bionic-21021400-a1c0533ad76",
},
{"key": "machine_type", "value": "e2-standard-32"},
{"key": "pool", "value": "ChromeOS"},
{"key": "role", "value": "legacy-release"},
{"key": "zone", "value": "us-central1-b"},
]
}
}
}
class BuildbucketV2Test(cros_test_lib.MockTestCase):
"""Tests for buildbucket_v2."""
# pylint: disable=attribute-defined-outside-init
def testCreatesClient(self) -> None:
ret = buildbucket_v2.BuildbucketV2(test_env=True)
self.assertIsInstance(ret.client, Client)
def testBatchCancelBuilds(self) -> None:
fake_field_mask = field_mask_pb2.FieldMask(paths=["properties"])
fake_batch_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.batch_cancel_build_request_fn = self.PatchObject(
builds_service_pb2, "BatchRequest", return_value=fake_batch_request
)
self.batch_cancel_function = self.PatchObject(client, "Batch")
bbv2.BatchCancelBuilds([1234, 1235], "test", "properties")
fake_builds = [
builds_service_pb2.BatchRequest.Request(
cancel_build=(
builds_service_pb2.CancelBuildRequest(
id=1234, summary_markdown="test", fields=fake_field_mask
),
),
),
builds_service_pb2.BatchRequest.Request(
cancel_build=(
builds_service_pb2.CancelBuildRequest(
id=1235, summary_markdown="test", fields=fake_field_mask
),
),
),
]
self.batch_cancel_build_request_fn.assert_called_with(
requests=fake_builds
)
self.batch_cancel_function.assert_called_with(fake_batch_request)
def testBatchGetBuilds(self) -> None:
fake_field_mask = field_mask_pb2.FieldMask(paths=["properties"])
fake_batch_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.batch_get_build_request_fn = self.PatchObject(
builds_service_pb2, "BatchRequest", return_value=fake_batch_request
)
self.batch_get_function = self.PatchObject(client, "Batch")
bbv2.BatchGetBuilds([1234, 1235], "properties")
fake_builds = [
builds_service_pb2.BatchRequest.Request(
get_build=(
builds_service_pb2.GetBuildRequest(
id=1234, fields=fake_field_mask
),
),
),
builds_service_pb2.BatchRequest.Request(
get_build=(
builds_service_pb2.GetBuildRequest(
id=1235, fields=fake_field_mask
),
),
),
]
self.batch_get_build_request_fn.assert_called_with(requests=fake_builds)
self.batch_get_function.assert_called_with(fake_batch_request)
def testBatchSearchBuilds(self) -> None:
fake_batch_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tag = common_pb2.StringPair(
key="cbb_master_buildbucket_id", value=str(1234)
)
build_predicate = builds_service_pb2.BuildPredicate(
builder=builder, tags=[tag]
)
client = bbv2.client
self.batch_search_build_request_fn = self.PatchObject(
builds_service_pb2, "BatchRequest", return_value=fake_batch_request
)
self.batch_search_function = self.PatchObject(client, "Batch")
search_request = [
builds_service_pb2.SearchBuildsRequest(predicate=build_predicate)
]
bbv2.BatchSearchBuilds(search_request)
fake_builds = [
builds_service_pb2.BatchRequest.Request(
search_builds=(
builds_service_pb2.SearchBuildsRequest(
predicate=build_predicate,
),
),
),
]
self.batch_search_build_request_fn.assert_called_with(
requests=fake_builds
)
self.batch_search_function.assert_called_with(fake_batch_request)
def testCancelBuildWithProperties(self) -> None:
fake_field_mask = field_mask_pb2.FieldMask(paths=["properties"])
fake_cancel_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.cancel_build_request_fn = self.PatchObject(
builds_service_pb2,
"CancelBuildRequest",
return_value=fake_cancel_build_request,
)
self.cancel_build_function = self.PatchObject(client, "CancelBuild")
bbv2.CancelBuild(1234, "test", "properties")
self.cancel_build_request_fn.assert_called_with(
id=1234, summary_markdown="test", fields=fake_field_mask
)
self.cancel_build_function.assert_called_with(fake_cancel_build_request)
def testCancelBuildWithoutProperties(self) -> None:
fake_cancel_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.cancel_build_request_fn = self.PatchObject(
builds_service_pb2,
"CancelBuildRequest",
return_value=fake_cancel_build_request,
)
self.cancel_build_function = self.PatchObject(client, "CancelBuild")
bbv2.CancelBuild(1234, "test")
self.cancel_build_request_fn.assert_called_with(
id=1234, summary_markdown="test", fields=None
)
self.cancel_build_function.assert_called_with(fake_cancel_build_request)
def testGetBuildWithMultipleProperties(self) -> None:
fake_field_mask = field_mask_pb2.FieldMask(
paths=["output.properties", "id", "status", "summary_markdown"]
)
fake_get_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.get_build_request_fn = self.PatchObject(
builds_service_pb2,
"GetBuildRequest",
return_value=fake_get_build_request,
)
self.get_build_function = self.PatchObject(client, "GetBuild")
bbv2.GetBuild(
"some-id", ["output.properties", "id", "status", "summary_markdown"]
)
self.get_build_request_fn.assert_called_with(
id="some-id", fields=fake_field_mask
)
self.get_build_function.assert_called_with(fake_get_build_request)
def testGetBuildWithOneProperty(self) -> None:
fake_field_mask = field_mask_pb2.FieldMask(paths=["output.properties"])
fake_get_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.get_build_request_fn = self.PatchObject(
builds_service_pb2,
"GetBuildRequest",
return_value=fake_get_build_request,
)
self.get_build_function = self.PatchObject(client, "GetBuild")
bbv2.GetBuild("some-id", "output.properties")
self.get_build_request_fn.assert_called_with(
id="some-id", fields=fake_field_mask
)
self.get_build_function.assert_called_with(fake_get_build_request)
def testGetBuildWithoutProperties(self) -> None:
fake_get_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.get_build_request_fn = self.PatchObject(
builds_service_pb2,
"GetBuildRequest",
return_value=fake_get_build_request,
)
self.get_build_function = self.PatchObject(client, "GetBuild")
bbv2.GetBuild("some-id")
self.get_build_request_fn.assert_called_with(id="some-id", fields=None)
self.get_build_function.assert_called_with(fake_get_build_request)
def testScheduleBuild(self) -> None:
fake_builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general", builder="test-builder"
)
fake_field_mask = field_mask_pb2.FieldMask(paths=["properties"])
fake_tag = common_pb2.StringPair(key="foo", value="bar")
fake_schedule_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.schedule_build_request_fn = self.PatchObject(
builds_service_pb2,
"ScheduleBuildRequest",
return_value=fake_schedule_build_request,
)
self.schedule_build_function = self.PatchObject(client, "ScheduleBuild")
bbv2.ScheduleBuild(
request_id="1234",
builder=fake_builder,
tags=fake_tag,
fields="properties",
critical=True,
)
self.schedule_build_request_fn.assert_called_with(
request_id="1234",
template_build_id=None,
builder=fake_builder,
properties=None,
gerrit_changes=None,
tags=fake_tag,
dimensions=None,
fields=fake_field_mask,
critical=common_pb2.YES,
)
self.schedule_build_function.assert_called_with(
fake_schedule_build_request
)
def testUpdateBuildWithProperties(self) -> None:
fake_update_mask = field_mask_pb2.FieldMask(paths=["number"])
fake_prop_mask = field_mask_pb2.FieldMask(paths=["properties"])
fake_build = build_pb2.Build(id=2341, number=1234)
fake_update_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.update_build_request_fn = self.PatchObject(
builds_service_pb2,
"UpdateBuildRequest",
return_value=fake_update_build_request,
)
self.update_build_function = self.PatchObject(client, "UpdateBuild")
bbv2.UpdateBuild(fake_build, "number", "properties")
self.update_build_request_fn.assert_called_with(
build=fake_build,
update_mask=fake_update_mask,
fields=fake_prop_mask,
)
self.update_build_function.assert_called_with(fake_update_build_request)
def testUpdateBuildWithoutProperties(self) -> None:
fake_update_mask = field_mask_pb2.FieldMask(paths=["number"])
fake_build = build_pb2.Build(id=2341, number=1234)
fake_update_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2()
client = bbv2.client
self.update_build_request_fn = self.PatchObject(
builds_service_pb2,
"UpdateBuildRequest",
return_value=fake_update_build_request,
)
self.update_build_function = self.PatchObject(client, "UpdateBuild")
bbv2.UpdateBuild(fake_build, "number")
self.update_build_request_fn.assert_called_with(
build=fake_build, update_mask=fake_update_mask, fields=None
)
self.update_build_function.assert_called_with(fake_update_build_request)
def testGetBuildStages(self) -> None:
"""Test the GetBuildStages functionality."""
bbv2 = buildbucket_v2.BuildbucketV2()
start_time = Timestamp()
start_time.GetCurrentTime()
step = step_pb2.Step(name="stage_name", start_time=start_time, status=2)
build_with_steps = build_pb2.Build(steps=[step])
get_build_fn = self.PatchObject(
bbv2, "GetBuild", return_value=build_with_steps
)
get_build_status_fn = self.PatchObject(
bbv2,
"GetBuildStatus",
return_value={"build_config": "something-paladin"},
)
expected_result = [
{
"name": "stage_name",
"start_time": datetime.fromtimestamp(start_time.seconds),
"finish_time": None,
"buildbucket_id": 1234,
"status": constants.BUILDER_STATUS_INFLIGHT,
"build_config": "something-paladin",
}
]
self.assertEqual(bbv2.GetBuildStages(1234), expected_result)
get_build_fn.assert_called_once_with(1234, properties="steps")
get_build_status_fn.assert_called_once_with(1234)
def testGetKilledChildBuildsWithValidId(self) -> None:
"""Test a valid query flow."""
bbv2 = buildbucket_v2.BuildbucketV2()
buildbucket_id = 1234
expected_child_builds = [8921795536486453568, 8921795536486453567]
fake_properties = Struct(
fields={
"killed_child_builds": Value(
string_value=str(expected_child_builds)
)
}
)
fake_output = build_pb2.Build.Output(properties=fake_properties)
fake_build = build_pb2.Build(id=1234, output=fake_output)
self.PatchObject(
buildbucket_v2.BuildbucketV2, "GetBuild", return_value=fake_build
)
builds = bbv2.GetKilledChildBuilds(buildbucket_id)
self.assertEqual(builds, expected_child_builds)
def testGetKilledChildBuildsWithInvalidId(self) -> None:
"""Test an unsuccessful query."""
bbv2 = buildbucket_v2.BuildbucketV2()
buildbucket_id = 1234
self.PatchObject(
buildbucket_v2.BuildbucketV2, "GetBuild", side_effect=ProtocolError
)
builds = bbv2.GetKilledChildBuilds(buildbucket_id)
self.assertIsNone(builds)
def testGetBuildStatusWithValidId(self) -> None:
"""Tests for GetBuildStatus with a valid ID."""
props_dict = {
"cidb_id": "1234",
"bot_id": "swarm-cros-34",
"cbb_branch": "master",
"cbb_config": "sludge-paladin-tryjob",
"cbb_master_build_id": "4321",
"platform_version": "11721.0.0",
"milestone_version": "74",
"full_version": "R74-11721.0.0-b3457724",
"critical": "1",
"build_type": "Try",
}
start_time = Timestamp()
start_time.GetCurrentTime()
fake_properties = Struct(
fields={
key: Value(string_value=value)
for key, value in props_dict.items()
}
)
fake_output = build_pb2.Build.Output(properties=fake_properties)
fake_build = build_pb2.Build(
id=1234, start_time=start_time, status=2, output=fake_output
)
self.PatchObject(
buildbucket_v2.BuildbucketV2, "GetBuild", return_value=fake_build
)
expected_valid_status = {
"build_config": "sludge-paladin-tryjob",
"start_time": datetime.fromtimestamp(start_time.seconds),
"finish_time": None,
"id": 1234,
"status": constants.BUILDER_STATUS_INFLIGHT,
"chrome_version": None,
"platform_version": "11721.0.0",
"milestone_version": "74",
"full_version": "R74-11721.0.0-b3457724",
"important": 1,
"buildbucket_id": 1234,
"summary": None,
"master_build_id": 4321,
"bot_hostname": "swarm-cros-34",
"builder_name": None,
"build_number": None,
"buildbot_generation": None,
"waterfall": None,
"deadline": None,
"build_type": "Try",
"metadata_url": None,
"toolchain_url": None,
"branch": "master",
}
bbv2 = buildbucket_v2.BuildbucketV2()
status = bbv2.GetBuildStatus(1234)
self.assertEqual(status, expected_valid_status)
def testGetBuildStatusWithInvalidId(self) -> None:
"""Test the function for an ID that doesn't exist in Buildbucket."""
expected_invalid_status = {
"build_config": None,
"start_time": None,
"finish_time": None,
"status": None,
"id": None,
"chrome_version": None,
"platform_version": None,
"milestone_version": None,
"full_version": None,
"important": None,
"buildbucket_id": 0,
"summary": None,
"master_build_id": None,
"bot_hostname": None,
"builder_name": None,
"build_number": None,
"buildbot_generation": None,
"waterfall": None,
"deadline": None,
"build_type": None,
"metadata_url": None,
"toolchain_url": None,
"branch": None,
}
self.PatchObject(
buildbucket_v2.BuildbucketV2, "GetBuild", side_effect=ProtocolError
)
bbv2 = buildbucket_v2.BuildbucketV2()
status = bbv2.GetBuildStatus(0)
self.assertEqual(status, expected_invalid_status)
def testSearchBuildExceptionCases(self) -> None:
"""Test scenarios where SearchBuild raises an Exception."""
bbv2 = buildbucket_v2.BuildbucketV2()
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tag = common_pb2.StringPair(
key="cbb_master_buildbucket_id", value=str(1234)
)
build_predicate = builds_service_pb2.BuildPredicate(
builder=builder, tags=[tag]
)
with self.assertRaises(AssertionError):
bbv2.SearchBuild(None, None, 100)
with self.assertRaises(AssertionError):
bbv2.SearchBuild(build_predicate, None, None)
with self.assertRaises(AssertionError):
bbv2.SearchBuild(build_predicate, "str_fields", 100)
def testSearchBuild(self) -> None:
"""Test redirection to the underlying RPC call."""
bbv2 = buildbucket_v2.BuildbucketV2()
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tag = common_pb2.StringPair(
key="cbb_master_buildbucket_id", value=str(1234)
)
build_predicate = builds_service_pb2.BuildPredicate(
builder=builder, tags=[tag]
)
fields = field_mask_pb2.FieldMask()
search_builds_fn = self.PatchObject(bbv2.client, "SearchBuilds")
bbv2.SearchBuild(build_predicate, fields=fields, page_size=123)
search_builds_fn.assert_called_once_with(
builds_service_pb2.SearchBuildsRequest(
predicate=build_predicate, fields=fields, page_size=123
)
)
def testGetBuildHistoryIgnoreIdFoundId(self) -> None:
"""Test GetBuildHistory ignore_build_id logic."""
# pylint: disable=unused-variable
bbv2 = buildbucket_v2.BuildbucketV2()
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tags = [
common_pb2.StringPair(key="cbb_config", value="something-paladin")
]
build_list = [build_pb2.Build(id=1234), build_pb2.Build(id=2341)]
search_fn = self.PatchObject(
bbv2,
"SearchBuild",
return_value=builds_service_pb2.SearchBuildsResponse(
builds=build_list
),
)
status_fn = self.PatchObject(bbv2, "GetBuildStatus")
bbv2.GetBuildHistory("something-paladin", 1, ignore_build_id=1234)
fake_predicate = builds_service_pb2.BuildPredicate(
builder=builder, tags=tags, create_time=None, build=None
)
search_fn.assert_called_once_with(fake_predicate, page_size=2)
status_fn.assert_called_once_with(2341)
def testGetBuildHistoryIgnoreIdWithoutId(self) -> None:
"""Test GetBuildHistory ignore_build_id logic when ID is absent."""
bbv2 = buildbucket_v2.BuildbucketV2()
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tags = [
common_pb2.StringPair(key="cbb_config", value="something-paladin")
]
build_list = [build_pb2.Build(id=1234), build_pb2.Build(id=2341)]
search_fn = self.PatchObject(
bbv2,
"SearchBuild",
return_value=builds_service_pb2.SearchBuildsResponse(
builds=build_list
),
)
status_fn = self.PatchObject(bbv2, "GetBuildStatus")
bbv2.GetBuildHistory("something-paladin", 1, ignore_build_id=1000)
fake_predicate = builds_service_pb2.BuildPredicate(
builder=builder, tags=tags, create_time=None, build=None
)
search_fn.assert_called_with(fake_predicate, page_size=2)
status_fn.assert_called_with(1234)
def testGetBuildHistoryOtherArgs(self) -> None:
"""Test GetBuildHistory's processing of (args - ignore_build_id)."""
builder = builder_common_pb2.BuilderID(
project="chromeos", bucket="general"
)
tags = [
common_pb2.StringPair(key="cbb_config", value="something-paladin"),
common_pb2.StringPair(key="cbb_branch", value="master"),
]
start_date = date(2019, 4, 16)
create_time = buildbucket_v2.DateToTimeRange(start_date)
fake_build = builds_service_pb2.BuildRange(start_build_id=1234)
fake_predicate = builds_service_pb2.BuildPredicate(
builder=builder,
tags=tags,
create_time=create_time,
build=fake_build,
)
bbv2 = buildbucket_v2.BuildbucketV2()
search_fn = self.PatchObject(bbv2, "SearchBuild")
self.PatchObject(bbv2, "GetBuildStatus")
bbv2.GetBuildHistory(
"something-paladin",
10,
start_date=start_date,
branch="master",
start_build_id=1234,
)
search_fn.assert_called_once_with(fake_predicate, page_size=10)
def testGetChildStatusesSuccess(self) -> None:
"""Test GetChildStatuses when RPC succeeds."""
bbv2 = buildbucket_v2.BuildbucketV2()
fake_search_build_response = builds_service_pb2.SearchBuildsResponse()
self.PatchObject(
bbv2, "SearchBuild", return_value=fake_search_build_response
)
self.assertEqual(bbv2.GetChildStatuses(1234), [])
fake_build = build_pb2.Build(id=2341)
fake_search_build_response = builds_service_pb2.SearchBuildsResponse(
builds=[fake_build]
)
self.PatchObject(
bbv2, "SearchBuild", return_value=fake_search_build_response
)
get_build_status = self.PatchObject(bbv2, "GetBuildStatus")
bbv2.GetChildStatuses(1234)
get_build_status.assert_called_once_with(2341)
def testGetStageFailures(self) -> None:
"""Test GetStageFailures logic."""
bbv2 = buildbucket_v2.BuildbucketV2()
fake_build_status = {
"buildbucket_id": 1234,
"status": "Passed!!",
"build_config": "something-paladin",
"important": True,
}
fake_stages = [
{"name": "stage_1", "status": constants.BUILDER_STATUS_PASSED},
{"name": "stage_2", "status": constants.BUILDER_STATUS_FAILED},
{"name": "stage_3", "status": constants.BUILDER_STATUS_FORGIVEN},
]
self.PatchObject(bbv2, "GetBuildStatus", return_value=fake_build_status)
self.PatchObject(bbv2, "GetBuildStages", return_value=fake_stages)
expected_answer = [
{
"stage_name": "stage_2",
"stage_status": constants.BUILDER_STATUS_FAILED,
"buildbucket_id": 1234,
"build_config": "something-paladin",
"build_status": "Passed!!",
"important": True,
}
]
self.assertEqual(bbv2.GetStageFailures(1234), expected_answer)
class StaticFunctionsTest(cros_test_lib.MockTestCase):
"""Test static functions in lib/buildbucket_v2.py."""
# pylint: disable=attribute-defined-outside-init
def testUpdateSelfBuildPropertiesNonBlocking(self) -> None:
self.logging_function = self.PatchObject(
cbuildbot_alerts, "PrintKitchenSetBuildProperty"
)
buildbucket_v2.UpdateSelfBuildPropertiesNonBlocking("key", "value")
self.logging_function.assert_called_with("key", "value")
def testUpdateSelfCommonBuildProperties(self) -> None:
self.underlying_function = self.PatchObject(
buildbucket_v2, "UpdateSelfBuildPropertiesNonBlocking"
)
fake_value = 123
fake_id = 8921795536486453568
buildbucket_v2.UpdateSelfCommonBuildProperties(critical=True)
self.underlying_function.assert_called_with("critical", True)
buildbucket_v2.UpdateSelfCommonBuildProperties(cidb_id=fake_value)
self.underlying_function.assert_called_with("cidb_id", fake_value)
buildbucket_v2.UpdateSelfCommonBuildProperties(
chrome_version=fake_value
)
self.underlying_function.assert_called_with(
"chrome_version", fake_value
)
buildbucket_v2.UpdateSelfCommonBuildProperties(
milestone_version=fake_value
)
self.underlying_function.assert_called_with(
"milestone_version", fake_value
)
buildbucket_v2.UpdateSelfCommonBuildProperties(
platform_version=fake_value
)
self.underlying_function.assert_called_with(
"platform_version", fake_value
)
buildbucket_v2.UpdateSelfCommonBuildProperties(full_version=fake_value)
self.underlying_function.assert_called_with("full_version", fake_value)
buildbucket_v2.UpdateSelfCommonBuildProperties(toolchain_url=fake_value)
self.underlying_function.assert_called_with("toolchain_url", fake_value)
buildbucket_v2.UpdateSelfCommonBuildProperties(build_type=fake_value)
self.underlying_function.assert_called_with("build_type", fake_value)
buildbucket_v2.UpdateSelfCommonBuildProperties(unibuild=True)
self.underlying_function.assert_called_with("unibuild", True)
buildbucket_v2.UpdateSelfCommonBuildProperties(suite_scheduling=True)
self.underlying_function.assert_called_with("suite_scheduling", True)
buildbucket_v2.UpdateSelfCommonBuildProperties(
killed_child_builds=[fake_id, fake_value]
)
self.underlying_function.assert_called_with(
"killed_child_builds", str([fake_id, fake_value])
)
buildbucket_v2.UpdateSelfCommonBuildProperties(board="grunt")
self.underlying_function.assert_called_with("board", "grunt")
buildbucket_v2.UpdateSelfCommonBuildProperties(
main_firmware_version="Google_Grunt.11031.62.0"
)
self.underlying_function.assert_called_with(
"main_firmware_version", "Google_Grunt.11031.62.0"
)
buildbucket_v2.UpdateSelfCommonBuildProperties(
ec_firmware_version="aleena_v2.1.108-9ca28c388"
)
self.underlying_function.assert_called_with(
"ec_firmware_version", "aleena_v2.1.108-9ca28c388"
)
def testUpdateBuildMetadata(self) -> None:
fake_dict = {
"version": {
"chrome": "chrome_version",
"milestone": "milestone_version",
"platform": "platform_version",
"full": "full_version",
},
"toolchain-url": "toolchain_url",
"build_type": "canary",
"important": True,
"unibuild": True,
}
self.PatchObject(
metadata_lib.CBuildbotMetadata, "GetDict", return_value=fake_dict
)
self.PatchObject(buildbucket_v2, "UpdateSelfCommonBuildProperties")
fake_metadata = metadata_lib.CBuildbotMetadata()
buildbucket_v2.UpdateBuildMetadata(fake_metadata)
buildbucket_v2.UpdateSelfCommonBuildProperties.assert_called_with(
critical=True,
chrome_version="chrome_version",
milestone_version="milestone_version",
platform_version="platform_version",
full_version="full_version",
toolchain_url="toolchain_url",
build_type="canary",
unibuild=True,
suite_scheduling=False,
channels=None,
)
def testBuildStepToDict(self) -> None:
"""Test the working of BuildStepToDict."""
build_values = {
"buildbucket_id": 1234,
"build_config": "something-paladin",
}
start_time = Timestamp()
start_time.GetCurrentTime()
step = step_pb2.Step(name="stage_name", start_time=start_time, status=2)
expected_result = {
"name": "stage_name",
"start_time": datetime.fromtimestamp(start_time.seconds),
"finish_time": None,
"buildbucket_id": 1234,
"status": constants.BUILDER_STATUS_INFLIGHT,
"build_config": "something-paladin",
}
self.assertEqual(
buildbucket_v2.BuildStepToDict(step, build_values), expected_result
)
def testDateToTimeRangeNoneInput(self) -> None:
self.assertIsNone(buildbucket_v2.DateToTimeRange(None))
def testDateToTimeRangeStartDate(self) -> None:
date_example = date(2019, 4, 15)
result = buildbucket_v2.DateToTimeRange(start_date=date_example)
self.assertEqual(result.start_time.seconds, 1555286400)
self.assertEqual(result.end_time.seconds, 0)
def testDateToTimeRangeEndDate(self) -> None:
date_example = date(2019, 4, 15)
result = buildbucket_v2.DateToTimeRange(end_date=date_example)
self.assertEqual(result.end_time.seconds, 1555372740)
self.assertEqual(result.start_time.seconds, 0)
def testGetStringPairValue(self) -> None:
bot_id = buildbucket_v2.GetStringPairValue(
SUCCESS_BUILD, ["infra", "swarming", "botDimensions"], "id"
)
self.assertEqual(bot_id, "chromeos-ci-test-bot")
pool = buildbucket_v2.GetStringPairValue(
SUCCESS_BUILD, ["infra", "swarming", "botDimensions"], "pool"
)
self.assertEqual(pool, "ChromeOS")
role = buildbucket_v2.GetStringPairValue(
SUCCESS_BUILD, ["infra", "swarming", "botDimensions"], "role"
)
self.assertEqual(role, "legacy-release")
def testGetBotId(self) -> None:
bot_id = buildbucket_v2.GetBotId(SUCCESS_BUILD)
self.assertEqual(bot_id, "chromeos-ci-test-bot")
def testGetScheduledBuildDict(self) -> None:
"""test GetScheduledBuildDict."""
config_name_1 = "config_name_1"
config_name_2 = "config_name_2"
config_name_3 = "config_name_3"
id_1 = "id_1"
id_2 = "id_2"
id_3 = "id_3"
slave_list = [
(config_name_1, id_1, 1),
(config_name_2, id_2, 2),
(config_name_3, id_3, 3),
]
build_dict = buildbucket_v2.GetScheduledBuildDict(slave_list)
self.assertEqual(len(build_dict), 3)
self.assertEqual(build_dict[config_name_1].buildbucket_id, id_1)
self.assertEqual(build_dict[config_name_2].buildbucket_id, id_2)
self.assertEqual(build_dict[config_name_3].buildbucket_id, id_3)
self.assertEqual(build_dict[config_name_1].retry, 0)
self.assertEqual(build_dict[config_name_2].retry, 0)
self.assertEqual(build_dict[config_name_3].retry, 0)
self.assertEqual(build_dict[config_name_1].created_ts, 1)
self.assertEqual(build_dict[config_name_2].created_ts, 2)
self.assertEqual(build_dict[config_name_3].created_ts, 3)
slave_list = [
(config_name_1, id_1, 1),
(config_name_2, id_2, 2),
(config_name_1, id_3, 3),
]
build_dict = buildbucket_v2.GetScheduledBuildDict(slave_list)
self.assertEqual(len(build_dict), 2)
self.assertEqual(build_dict[config_name_1].buildbucket_id, id_3)
self.assertEqual(build_dict[config_name_2].buildbucket_id, id_2)
self.assertEqual(build_dict[config_name_1].retry, 1)
self.assertEqual(build_dict[config_name_2].retry, 0)
self.assertEqual(build_dict[config_name_1].created_ts, 3)
self.assertEqual(build_dict[config_name_2].created_ts, 2)
slave_list = [
(config_name_1, id_1, 3),
(config_name_2, id_2, 2),
(config_name_1, id_3, 1),
]
build_dict = buildbucket_v2.GetScheduledBuildDict(slave_list)
self.assertEqual(len(build_dict), 2)
self.assertEqual(build_dict[config_name_1].buildbucket_id, id_1)
self.assertEqual(build_dict[config_name_2].buildbucket_id, id_2)
self.assertEqual(build_dict[config_name_1].retry, 1)
self.assertEqual(build_dict[config_name_2].retry, 0)
self.assertEqual(build_dict[config_name_1].created_ts, 3)
self.assertEqual(build_dict[config_name_2].created_ts, 2)
build_dict = buildbucket_v2.GetScheduledBuildDict([])
self.assertEqual(build_dict, {})
build_dict = buildbucket_v2.GetScheduledBuildDict(None)
self.assertEqual(build_dict, {})
def testGetBuildInfoDict(self) -> None:
"""Test GetBuildInfoDict with metadata and config."""
metadata = metadata_lib.CBuildbotMetadata()
slaves = [
("config_1", "bb_id_1", 0),
("config_1", "bb_id_2", 1),
("config_2", "bb_id_3", 2),
]
metadata.ExtendKeyListWithList(
constants.METADATA_SCHEDULED_IMPORTANT_SLAVES, slaves
)
buildbucket_info_dict = buildbucket_v2.GetBuildInfoDict(metadata)
self.assertEqual(len(buildbucket_info_dict), 2)
self.assertEqual(
buildbucket_info_dict["config_1"],
buildbucket_v2.BuildbucketInfo("bb_id_2", 1, 1, None, None),
)
self.assertEqual(
buildbucket_info_dict["config_2"],
buildbucket_v2.BuildbucketInfo("bb_id_3", 0, 2, None, None),
)
buildbucket_info_dict_with_experimental = (
buildbucket_v2.GetBuildInfoDict(
metadata, exclude_experimental=False
)
)
self.assertEqual(len(buildbucket_info_dict), 2)
self.assertEqual(
buildbucket_info_dict_with_experimental["config_1"],
buildbucket_v2.BuildbucketInfo("bb_id_2", 1, 1, None, None),
)
self.assertEqual(
buildbucket_info_dict_with_experimental["config_2"],
buildbucket_v2.BuildbucketInfo("bb_id_3", 0, 2, None, None),
)
metadata.UpdateWithDict(
{constants.METADATA_EXPERIMENTAL_BUILDERS: ["config_2"]}
)
buildbucket_info_dict = buildbucket_v2.GetBuildInfoDict(metadata)
self.assertEqual(len(buildbucket_info_dict), 1)
self.assertEqual(
buildbucket_info_dict["config_1"],
buildbucket_v2.BuildbucketInfo("bb_id_2", 1, 1, None, None),
)
buildbucket_info_dict_with_experimental = (
buildbucket_v2.GetBuildInfoDict(
metadata, exclude_experimental=False
)
)
self.assertEqual(len(buildbucket_info_dict_with_experimental), 2)
self.assertEqual(
buildbucket_info_dict_with_experimental["config_1"],
buildbucket_v2.BuildbucketInfo("bb_id_2", 1, 1, None, None),
)
self.assertEqual(
buildbucket_info_dict_with_experimental["config_2"],
buildbucket_v2.BuildbucketInfo("bb_id_3", 0, 2, None, None),
)
def testGetBuildbucketIds(self) -> None:
"""Test GetBuildbucketIds with metadata and config."""
metadata = metadata_lib.CBuildbotMetadata()
slaves = [
("config_1", "bb_id_1", 0),
("config_1", "bb_id_2", 1),
("config_2", "bb_id_3", 2),
]
metadata.ExtendKeyListWithList(
constants.METADATA_SCHEDULED_IMPORTANT_SLAVES, slaves
)
buildbucket_ids = buildbucket_v2.GetBuildbucketIds(metadata)
self.assertTrue("bb_id_2" in buildbucket_ids)
self.assertTrue("bb_id_3" in buildbucket_ids)
def testCredentials(self) -> None:
fake_get_build_request = object()
bbv2 = buildbucket_v2.BuildbucketV2(
access_token_retriever=lambda: "some-token"
)
client = bbv2.client
self.PatchObject(
builds_service_pb2,
"GetBuildRequest",
return_value=fake_get_build_request,
)
get_build_function = self.PatchObject(client, "GetBuild")
bbv2.GetBuild("some-id")
class DisableAuthFn:
"""An object that can be compared to a function"""
def __eq__(self, fn: Any) -> bool:
request = new_request("a", "b", "c", "d", "e")
return not fn(request).include_auth
get_build_function.assert_called_with(
fake_get_build_request,
metadata=dict(Authorization="Bearer some-token"),
credentials=DisableAuthFn(),
)