blob: e4e1de94a6b3fd1b16dbdb04c411560b00e2a148 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright (c) 2012 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 remote_try.py."""
from __future__ import print_function
import json
import mock
from chromite.lib import auth
from chromite.lib import buildbucket_lib
from chromite.lib import constants
from chromite.lib import cros_test_lib
from chromite.lib import git
from chromite.lib import remote_try
# Tests need internal access.
# pylint: disable=protected-access
class RemoteTryHelperTestsBase(cros_test_lib.MockTestCase):
"""Tests for RemoteTryJob."""
BRANCH = 'test-branch'
PATCHES = ('5555', '6666')
BUILD_CONFIGS = ('amd64-generic-paladin', 'arm-generic-paladin')
UNKNOWN_CONFIGS = ('unknown-config')
BUILD_GROUP = 'display'
PASS_THROUGH_ARGS = ['funky', 'cold', 'medina']
TEST_EMAIL = 'explicit_email'
MASTER_BUILDBUCKET_ID = 'master_bb_id'
def setUp(self):
self.maxDiff = None
self.PatchObject(git, 'GetProjectUserEmail', return_value='default_email')
def _CreateJobMin(self):
return remote_try.RemoteTryJob(
self.BUILD_CONFIGS,
self.BUILD_GROUP,
'description')
def _CreateJobMax(self):
return remote_try.RemoteTryJob(
self.BUILD_CONFIGS,
self.BUILD_GROUP,
'description',
branch=self.BRANCH,
pass_through_args=self.PASS_THROUGH_ARGS,
local_patches=(), # TODO: Populate/test these, somehow.
committer_email=self.TEST_EMAIL,
swarming=True,
master_buildbucket_id=self.MASTER_BUILDBUCKET_ID)
def _CreateJobUnknown(self):
return remote_try.RemoteTryJob(
self.UNKNOWN_CONFIGS,
self.BUILD_GROUP,
'description')
class RemoteTryHelperTestsMock(RemoteTryHelperTestsBase):
"""Perform real buildbucket requests against a fake instance."""
def setUp(self):
# This mocks out the class, then creates a return_value for a function on
# instances of it. We do this instead of just mocking out the function to
# ensure not real network requests are made in other parts of the class.
client_mock = self.PatchObject(buildbucket_lib, 'BuildbucketClient')
client_mock().PutBuildRequest.return_value = {
'build': {'id': 'fake_buildbucket_id'}
}
def testDefaultDescription(self):
"""Verify job description formatting."""
description = remote_try.DefaultDescription(self.BRANCH, self.PATCHES)
self.assertEqual(description, '[test-branch] 5555,6666')
def testDefaultEmail(self):
"""Verify a default discovered email address."""
job = self._CreateJobMin()
# Verify default email detection.
self.assertEqual(job.user_email, 'default_email')
def testExplicitEmail(self):
"""Verify an explicitly set email address."""
job = self._CreateJobMax()
# Verify explicit email detection.
self.assertEqual(job.user_email, self.TEST_EMAIL)
def testMinRequestBody(self):
"""Verify our request body with min options."""
body = self._CreateJobMin()._GetRequestBody(self.BUILD_CONFIGS[0])
self.assertEqual(body, {
'parameters_json': mock.ANY,
'bucket': 'master.chromiumos.tryserver',
'tags': [
'cbb_display_label:display',
'cbb_branch:master',
'cbb_config:amd64-generic-paladin',
'cbb_master_build_id:',
'cbb_email:default_email',
]
})
parameters_parsed = json.loads(body['parameters_json'])
self.assertEqual(parameters_parsed, {
'builder_name': 'Generic',
'properties': {
'extra_args': [],
'cbb_extra_args': [],
'name': 'description',
'owners': ['default_email'],
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'email': ['default_email'],
'cbb_config': 'amd64-generic-paladin',
'user': mock.ANY,
}
})
def testMaxRequestBody(self):
"""Verify our request body with max options."""
self.maxDiff = None
body = self._CreateJobMax()._GetRequestBody(self.BUILD_CONFIGS[0])
self.assertEqual(body, {
'parameters_json': mock.ANY,
'bucket': 'luci.chromeos.general',
'tags': [
'cbb_display_label:display',
'cbb_branch:test-branch',
'cbb_config:amd64-generic-paladin',
'cbb_master_build_id:master_bb_id',
'cbb_email:explicit_email',
]
})
parameters_parsed = json.loads(body['parameters_json'])
self.assertEqual(parameters_parsed, {
'builder_name': 'Generic',
'properties': {
'extra_args': ['funky', 'cold', 'medina'],
'cbb_extra_args': ['funky', 'cold', 'medina'],
'name': 'description',
'owners': ['explicit_email'],
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'email': ['explicit_email'],
'cbb_config': 'amd64-generic-paladin',
'user': mock.ANY,
}
})
def testUnknownRequestBody(self):
"""Verify our request body with max options."""
self.maxDiff = None
body = self._CreateJobUnknown()._GetRequestBody('unknown-config')
self.assertEqual(body, {
'parameters_json': mock.ANY,
'bucket': 'master.chromiumos.tryserver',
'tags': [
'cbb_display_label:display',
'cbb_branch:master',
'cbb_config:unknown-config',
'cbb_master_build_id:',
'cbb_email:default_email',
]
})
parameters_parsed = json.loads(body['parameters_json'])
self.assertEqual(parameters_parsed, {
'builder_name': 'Generic',
'properties': {
'extra_args': [],
'cbb_extra_args': [],
'name': 'description',
'owners': ['default_email'],
'bot': 'unknown-config',
'email': ['default_email'],
'cbb_config': 'unknown-config',
'user': mock.ANY,
}
})
def testMinDryRun(self):
"""Do a dryrun of posting the request, min options."""
job = self._CreateJobMin()
job._PostConfigsToBuildBucket(testjob=True, dryrun=True)
# TODO: Improve coverage to all of Submit. Verify behavior.
def testMaxDryRun(self):
"""Do a dryrun of posting the request, max options."""
job = self._CreateJobMax()
job._PostConfigsToBuildBucket(testjob=True, dryrun=True)
# TODO: Improve coverage to all of Submit. Verify behavior.
class RemoteTryHelperTestsNetork(RemoteTryHelperTestsBase):
"""Perform real buildbucket requests against a test instance."""
def verifyBuildbucketRequest(self,
buildbucket_id,
expected_bucket,
expected_tags,
expected_parameters):
"""Verify the contents of a push to the TEST buildbucket instance.
Args:
buildbucket_id: Id to verify.
expected_bucket: Bucket the push was supposed to go to as a string.
expected_tags: List of buildbucket tags as strings.
expected_parameters: Python dict equivalent to json string in
parameters_json.
"""
buildbucket_client = buildbucket_lib.BuildbucketClient(
auth.GetAccessToken, buildbucket_lib.BUILDBUCKET_TEST_HOST,
service_account_json=buildbucket_lib.GetServiceAccount(
constants.CHROMEOS_SERVICE_ACCOUNT))
request = buildbucket_client.GetBuildRequest(buildbucket_id, False)
self.assertEqual(request['build']['id'], buildbucket_id)
self.assertEqual(request['build']['bucket'], expected_bucket)
self.assertItemsEqual(request['build']['tags'], expected_tags)
request_parameters = json.loads(request['build']['parameters_json'])
self.assertEqual(request_parameters, expected_parameters)
@cros_test_lib.NetworkTest()
def testMinTestBucket(self):
"""Talk to a test buildbucket instance with min job settings."""
# Submit jobs
job = self._CreateJobMin()
job.Submit(testjob=True)
buildbucket_ids = job.buildbucket_ids
self.verifyBuildbucketRequest(
buildbucket_ids[0],
'master.chromiumos.tryserver',
[
'builder:Generic',
'cbb_branch:master',
'cbb_display_label:display',
'cbb_config:amd64-generic-paladin',
'cbb_email:default_email',
'cbb_master_build_id:',
],
{
'builder_name': 'Generic',
'properties': {
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'cbb_config': 'amd64-generic-paladin',
'cbb_extra_args': [],
'email': ['default_email'],
'extra_args': [],
'name': 'description',
'owners': ['default_email'],
'user': mock.ANY,
},
})
self.verifyBuildbucketRequest(
buildbucket_ids[1],
'master.chromiumos.tryserver',
[
'builder:Generic',
'cbb_branch:master',
'cbb_display_label:display',
'cbb_config:arm-generic-paladin',
'cbb_email:default_email',
'cbb_master_build_id:',
],
{
'builder_name': 'Generic',
'properties': {
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'cbb_config': 'arm-generic-paladin',
'cbb_extra_args': [],
'email': ['default_email'],
'extra_args': [],
'name': 'description',
'owners': ['default_email'],
'user': mock.ANY,
},
})
# Verify live URLs.
job_links = job.GetTrybotWaterfallLinks()
self.assertEqual(job_links, [
('http://cros-goldeneye/chromeos/healthmonitoring/'
'buildDetails?buildbucketId=%s' % buildbucket_ids[0]),
('http://cros-goldeneye/chromeos/healthmonitoring/'
'buildDetails?buildbucketId=%s' % buildbucket_ids[1]),
('https://uberchromegw.corp.google.com/i/chromiumos.tryserver/'
'waterfall?committer=default_email&builder=paladin'),
])
@cros_test_lib.NetworkTest()
def testMaxTestBucket(self):
"""Talk to a test buildbucket instance with max job settings."""
# Submit jobs
job = self._CreateJobMax()
job.Submit(testjob=True)
buildbucket_ids = job.buildbucket_ids
# Verify buildbucket contents.
self.verifyBuildbucketRequest(
buildbucket_ids[0],
'luci.chromeos.general',
[
'builder:Generic',
'cbb_branch:test-branch',
'cbb_display_label:display',
'cbb_config:amd64-generic-paladin',
'cbb_email:explicit_email',
'cbb_master_build_id:master_bb_id',
],
{
'builder_name': 'Generic',
'properties': {
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'cbb_config': 'amd64-generic-paladin',
'cbb_extra_args': ['funky', 'cold', 'medina'],
'email': ['explicit_email'],
'extra_args': ['funky', 'cold', 'medina'],
'name': 'description',
'owners': ['explicit_email'],
'user': mock.ANY,
},
})
self.verifyBuildbucketRequest(
buildbucket_ids[1],
'luci.chromeos.general',
[
'builder:Generic',
'cbb_branch:test-branch',
'cbb_display_label:display',
'cbb_config:arm-generic-paladin',
'cbb_email:explicit_email',
'cbb_master_build_id:master_bb_id',
],
{
'builder_name': 'Generic',
'properties': {
'bot': ['amd64-generic-paladin', 'arm-generic-paladin'],
'cbb_config': 'arm-generic-paladin',
'cbb_extra_args': ['funky', 'cold', 'medina'],
'email': ['explicit_email'],
'extra_args': ['funky', 'cold', 'medina'],
'name': 'description',
'owners': ['explicit_email'],
'user': mock.ANY,
},
})
# Verify live URLs.
job_links = job.GetTrybotWaterfallLinks()
self.assertEqual(len(buildbucket_ids), len(job_links))
for buildbucket_id, link in zip(buildbucket_ids, job_links):
self.assertEqual(
link,
('http://cros-goldeneye/chromeos/healthmonitoring/buildDetails?'
'buildbucketId=%s' %
buildbucket_id)
)
# pylint: disable=protected-access
def testPostConfigsToBuildBucket(self):
"""Check syntax for PostConfigsToBuildBucket."""
self.PatchObject(auth, 'Login')
self.PatchObject(auth, 'Token')
self.PatchObject(remote_try.RemoteTryJob, '_PutConfigToBuildBucket')
remote_try_job = remote_try.RemoteTryJob(
['build_config'],
'display_label',
remote_description='description')
remote_try_job._PostConfigsToBuildBucket(testjob=True, dryrun=True)
def testGetRequestBody(self):
"""Test GetRequestBody."""
remote_try_job = remote_try.RemoteTryJob(
['lumpy-pre-cq', 'lumpy-paladin'],
'display_label',
remote_description='description')
body = remote_try_job._GetRequestBody('lumpy-pre-cq')
self.assertTrue('build_type:pre_cq' in body['tags'])
body = remote_try_job._GetRequestBody('lumpy-paladin')
self.assertFalse('build_type:pre_cq' in body['tags'])