| Index: dashboard/dashboard/update_bug_with_results_test.py
|
| diff --git a/dashboard/dashboard/update_bug_with_results_test.py b/dashboard/dashboard/update_bug_with_results_test.py
|
| index 67a3ad1f882a21e7726e0327147caaa358e704f4..14b7ca18241e1c330ba1db20620cf1dfa7d5acb6 100644
|
| --- a/dashboard/dashboard/update_bug_with_results_test.py
|
| +++ b/dashboard/dashboard/update_bug_with_results_test.py
|
| @@ -1,7 +1,9 @@
|
| -# Copyright 2015 The Chromium Authors. All rights reserved.
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| +import copy
|
| +import datetime
|
| import json
|
| import unittest
|
|
|
| @@ -21,183 +23,52 @@ from dashboard.models import anomaly
|
| from dashboard.models import bug_data
|
| from dashboard.models import try_job
|
|
|
| -# TODO(qyearsley): Shorten this module.
|
| -# See https://github.com/catapult-project/catapult/issues/1917
|
| -# pylint: disable=too-many-lines
|
| -
|
| -# Bisect log with multiple potential culprits with different authors.
|
| -_BISECT_LOG_MULTI_OWNER = """
|
| -@@@STEP_CURSOR Results@@@
|
| -@@@STEP_STARTED@@@
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total
|
| -Relative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 99.9%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000
|
| -
|
| -Subject : Subject 2
|
| -Author : prasadv, prasadv@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Date : Sat, 22 Jun 2013 00:57:48 +0000
|
| -
|
| -Subject : Subject 3
|
| -Author : qyearsley@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Date : Sat, 22 Jun 2013 00:55:52 +0000
|
| -"""
|
| -
|
| -# Bisect log with multiple potential culprits but same Author.
|
| -_BISECT_LOG_MULTI_SAME_OWNER = """
|
| -@@@STEP_CURSOR Results@@@
|
| -@@@STEP_STARTED@@@
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total
|
| -Relative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 99.9%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000
|
| -
|
| -Subject : Subject 2
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Date : Sat, 22 Jun 2013 00:57:48 +0000:55:52 +0000
|
| -"""
|
| -
|
| -# Bisect log with single potential culprits.
|
| -_BISECT_LOG_SINGLE_OWNER = """
|
| -@@@STEP_CURSOR Results@@@
|
| -@@@STEP_STARTED@@@
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total
|
| -Relative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 100%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Commit : d6432657771a9fd720179d8c3dd64c8daee025c7
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000
|
| -"""
|
| -
|
| -_EXPECTED_BISECT_LOG_SINGLE_OWNER = """
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total
|
| -Relative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 100%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Commit : d6432657771a9fd720179d8c3dd64c8daee025c7
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000"""
|
| -
|
| -_EXPECTED_BISECT_RESULTS_ON_BUG = """
|
| -==== Auto-CCing suspected CL author sullivan@google.com ====
|
| -
|
| -Hi sullivan@google.com, the bisect results pointed to your CL below as possibly
|
| -causing a regression. Please have a look at this info and see whether
|
| -your CL be related.
|
| -
|
| -Bisect job status: Completed
|
| -Bisect job ran on: win_perf_bisect
|
| -
|
| -
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total\nRelative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 100%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20798
|
| -Commit : d6432657771a9fd720179d8c3dd64c8daee025c7
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000
|
| -
|
| -Buildbot stdio: http://build.chromium.org/513
|
| -Job details: https://test-rietveld.appspot.com/200037
|
| -"""
|
| -
|
| -_BISECT_LOG_FAILED_REVISION = """
|
| -@@@STEP_CURSOR Results@@@
|
| -@@@STEP_STARTED@@@
|
| -
|
| -===== BISECT JOB RESULTS =====
|
| -Status: Positive
|
| -
|
| -Test Command: python tools/perf/run_benchmark -v --browser=release sunspider
|
| -Test Metric: Total/Total
|
| -Relative Change: 1.23% (+/-1.26%)
|
| -Estimated Confidence: 99.9%
|
| -
|
| -===== SUSPECTED CL(s) =====
|
| -Subject : Subject 1
|
| -Author : sullivan@google.com
|
| -Link : http://src.chromium.org/viewvc/chrome?view=revision&revision=20799
|
| -Commit : a80773bb263a9706cc8ee4e3f336d2d3d28fadd8
|
| -Date : Sat, 22 Jun 2013 00:59:35 +0000
|
| -"""
|
| -
|
| -_BISECT_LOG_PARTIAL_RESULT = """
|
| -===== PARTIAL RESULTS =====
|
| -Depot Commit SHA Mean Std. Error State
|
| -chromium 282472 91730.00 +-0.00 Bad
|
| -
|
| -chromium 282469 92973.00 +-0.00 Good
|
| -chromium 282460 93468.00 +-0.00 Good
|
| -
|
| -
|
| -"""
|
| -
|
| -_EXPECTED_BISECT_LOG_PARTIAL_RESULT = u"""Bisect job status: Failure with \
|
| -partial results
|
| -Bisect job ran on: win_perf_bisect
|
| -
|
| -Completed 1/2 builds.
|
| -Run time: 724/720 minutes.
|
| -Bisect timed out! Try again with a smaller revision range.
|
| -Failed steps: slave_steps, Working on def
|
| -
|
| -===== PARTIAL RESULTS =====
|
| -Depot Commit SHA Mean Std. Error State
|
| -chromium 282472 91730.00 +-0.00 Bad
|
| -
|
| -chromium 282469 92973.00 +-0.00 Good
|
| -chromium 282460 93468.00 +-0.00 Good
|
| -
|
| -Buildbot stdio: http://build.chromium.org/builders/515
|
| -Job details: https://test-rietveld.appspot.com/200039
|
| -"""
|
| +_SAMPLE_BISECT_RESULTS_JSON = {
|
| + 'try_job_id': 6789,
|
| + 'bug_id': 4567,
|
| + 'status': 'completed',
|
| + 'bisect_bot': 'linux',
|
| + 'buildbot_log_url': '',
|
| + 'command': ('tools/perf/run_benchmark -v '
|
| + '--browser=release page_cycler.intl_ar_fa_he'),
|
| + 'metric': 'warm_times/page_load_time',
|
| + 'change': '',
|
| + 'score': 99.9,
|
| + 'good_revision': '306475',
|
| + 'bad_revision': '306478',
|
| + 'warnings': None,
|
| + 'abort_reason': None,
|
| + 'issue_url': 'https://issue_url/123456',
|
| + 'culprit_data': {
|
| + 'subject': 'subject',
|
| + 'author': 'author',
|
| + 'email': 'author@email.com',
|
| + 'cl_date': '1/2/2015',
|
| + 'commit_info': 'commit_info',
|
| + 'revisions_links': ['http://src.chromium.org/viewvc/chrome?view='
|
| + 'revision&revision=20798'],
|
| + 'cl': '123'
|
| + },
|
| + 'revision_data': [
|
| + {
|
| + 'depot_name': 'chromium',
|
| + 'deps_revision': 1234,
|
| + 'commit_pos': 1234,
|
| + 'mean_value': 70,
|
| + 'std_dev': 0,
|
| + 'values': [70, 70, 70],
|
| + 'result': 'good'
|
| + }, {
|
| + 'depot_name': 'chromium',
|
| + 'deps_revision': 1235,
|
| + 'commit_pos': 1235,
|
| + 'mean_value': 80,
|
| + 'std_dev': 0,
|
| + 'values': [80, 80, 80],
|
| + 'result': 'bad'
|
| + }
|
| + ]
|
| +}
|
|
|
| _REVISION_RESPONSE = """
|
| <html xmlns=....>
|
| @@ -225,32 +96,6 @@ dromaeo.jslibstylejquery --profiler=trace',
|
| 'max_time_minutes': '120'
|
| }"""
|
|
|
| -_PERF_LOG_EXPECTED_TITLE_1 = 'With Patch - Profiler Data[0]'
|
| -_PERF_LOG_EXPECTED_TITLE_2 = 'Without Patch - Profiler Data[0]'
|
| -_PERF_LOG_EXPECTED_PROFILER_LINK1 = (
|
| - 'https://console.developers.google.com/m/cloudstorage/b/chrome-telemetry/o/'
|
| - 'profiler-file-id_0-2014-11-27_14-08-5560487.json')
|
| -_PERF_LOG_EXPECTED_PROFILER_LINK2 = (
|
| - 'https://console.developers.google.com/m/cloudstorage/b/chrome-telemetry/o/'
|
| - 'profiler-file-id_0-2014-11-27_14-10-1644780.json')
|
| -_PERF_LOG_EXPECTED_HTML_LINK = (
|
| - 'http://storage.googleapis.com/chromium-telemetry/html-results/'
|
| - 'results-2014-11-27_14-10-21')
|
| -_PERF_LOG_WITH_RESULTS = """
|
| -@@@STEP_CLOSED@@@
|
| -
|
| -
|
| -@@@STEP_LINK@HTML Results@%s@@@
|
| -
|
| -
|
| -@@@STEP_LINK@%s@%s@@@
|
| -
|
| -
|
| -@@@STEP_LINK@%s@%s@@@
|
| -""" % (_PERF_LOG_EXPECTED_HTML_LINK, _PERF_LOG_EXPECTED_TITLE_1,
|
| - _PERF_LOG_EXPECTED_PROFILER_LINK1, _PERF_LOG_EXPECTED_TITLE_2,
|
| - _PERF_LOG_EXPECTED_PROFILER_LINK2)
|
| -
|
| _ISSUE_RESPONSE = """
|
| {
|
| "description": "Issue Description.",
|
| @@ -276,128 +121,9 @@ _ISSUE_RESPONSE = """
|
| }
|
| """
|
|
|
| -_BISECT_LOG_INFRA_FAILURE = 'Failed to produce build'
|
| -
|
| -# Globals that are set in mock functions and then checked in tests.
|
| -_TEST_RECEIVED_EMAIL_RESULTS = None
|
| -_TEST_RECEIVED_EMAIL = None
|
| -
|
| -
|
| -def _MockGetJobStatus(job):
|
| - id_to_response_map = {
|
| - # Complete
|
| - '1234567': {
|
| - 'result': 'SUCCESS',
|
| - 'result_details': {
|
| - 'buildername': 'Fake_Bot',
|
| - },
|
| - 'url': 'http://build.chromium.org/bb1234567',
|
| - 'status': 'COMPLETED',
|
| - },
|
| - # In progress
|
| - '11111': {
|
| - 'result_details': {
|
| - 'buildername': 'Fake_Bot',
|
| - },
|
| - 'url': 'http://build.chromium.org/bb11111',
|
| - 'status': 'STARTED',
|
| - },
|
| - # Failed
|
| - '66666': {
|
| - 'result': 'FAILURE',
|
| - 'result_details': {
|
| - 'buildername': 'Fake_Bot',
|
| - },
|
| - 'url': 'http://build.chromium.org/bb66666',
|
| - 'status': 'COMPLETED',
|
| - },
|
| - }
|
| - return id_to_response_map.get(str(job.buildbucket_job_id))
|
| -
|
|
|
| def _MockFetch(url=None):
|
| url_to_response_map = {
|
| - 'https://test-rietveld.appspot.com/api/200034/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/508'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/302304/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '2',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/509'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/100001/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '6',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/510'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/200035/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/511'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/200036/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/512'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/200037/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/513'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/200038/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/514'}]})
|
| - ],
|
| - 'https://test-rietveld.appspot.com/api/200039/1': [
|
| - 200,
|
| - json.dumps({'try_job_results': [{
|
| - 'result': '0',
|
| - 'builder': 'win_perf_bisect',
|
| - 'url': 'http://build.chromium.org/builders/515'}]})
|
| - ],
|
| - 'http://build.chromium.org/json/builders/515': [
|
| - 200,
|
| - json.dumps({
|
| - 'steps': [{'name': 'Working on abc', 'results': [0]},
|
| - {'name': 'Working on def', 'results': [2]}],
|
| - 'times': [1411501756.293642, 1411545237.89049],
|
| - 'text': ['failed', 'slave_steps', 'failed', 'Working on def']})
|
| - ],
|
| - 'http://build.chromium.org/bb1234567/steps/Results/logs/stdio/text': [
|
| - 200, _BISECT_LOG_SINGLE_OWNER
|
| - ],
|
| - 'http://build.chromium.org/bb66666': [
|
| - 200,
|
| - json.dumps({
|
| - 'steps': [{'name': 'Working on abc', 'results': [0]},
|
| - {'name': 'Working on def', 'results': [2]}],
|
| - 'times': [1411501756.293642, 1411545237.89049],
|
| - 'text': ['failed', 'slave_steps', 'failed', 'Working on def']})
|
| - ],
|
| - ('http://build.chromium.org/builders/bb66666'
|
| - '/steps/Results/logs/stdio/text'): [404, ''],
|
| - 'http://build.chromium.org/json/builders/516': [
|
| - 200,
|
| - json.dumps({'steps': [{'name': 'gclient', 'results': [2]}]})
|
| - ],
|
| 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20798': [
|
| 200, _REVISION_RESPONSE
|
| ],
|
| @@ -407,43 +133,6 @@ def _MockFetch(url=None):
|
| 'https://codereview.chromium.org/api/17504006': [
|
| 200, json.dumps(json.loads(_ISSUE_RESPONSE))
|
| ],
|
| - 'http://build.chromium.org/508/steps/Results/logs/stdio/text': [
|
| - 200, '===== BISECT JOB RESULTS ====='
|
| - ],
|
| - 'http://build.chromium.org/509/steps/Results/logs/stdio/text': [
|
| - 200, 'BISECT FAILURE! '
|
| - ],
|
| - 'http://build.chromium.org/511/steps/Results/logs/stdio/text': [
|
| - 200, _BISECT_LOG_MULTI_OWNER
|
| - ],
|
| - 'http://build.chromium.org/512/steps/Results/logs/stdio/text': [
|
| - 200, _BISECT_LOG_MULTI_SAME_OWNER
|
| - ],
|
| - 'http://build.chromium.org/513/steps/Results/logs/stdio/text': [
|
| - 200, _BISECT_LOG_SINGLE_OWNER
|
| - ],
|
| - 'http://build.chromium.org/514/steps/Results/logs/stdio/text': [
|
| - 200, _BISECT_LOG_FAILED_REVISION
|
| - ],
|
| - 'http://build.chromium.org/builders/515/steps/Results/logs/stdio/text': [
|
| - 404, ''
|
| - ],
|
| - 'http://build.chromium.org/builders/515/steps/Working%20on%20abc/logs/'
|
| - 'stdio/text': [
|
| - 200, _BISECT_LOG_PARTIAL_RESULT
|
| - ],
|
| - 'http://build.chromium.org/builders/516/steps/slave_steps/logs/stdio/'
|
| - 'text': [
|
| - 200, _BISECT_LOG_INFRA_FAILURE
|
| - ],
|
| - 'http://build.chromium.org/508/steps/Running%20Bisection/logs/stdio/'
|
| - 'text': [
|
| - 200, _PERF_LOG_WITH_RESULTS
|
| - ],
|
| - 'http://build.chromium.org/511/steps/Running%20Bisection/logs/stdio/'
|
| - 'text': [
|
| - 200, ''
|
| - ],
|
| }
|
|
|
| if url not in url_to_response_map:
|
| @@ -454,21 +143,6 @@ def _MockFetch(url=None):
|
| return testing_common.FakeResponseObject(response_code, response)
|
|
|
|
|
| -def _MockMakeRequest(path, method): # pylint: disable=unused-argument
|
| - url = 'https://test-rietveld.appspot.com/' + path
|
| - return _MockFetch(url=url)
|
| -
|
| -
|
| -def _MockSendPerfTryJobEmail(_, results):
|
| - global _TEST_RECEIVED_EMAIL_RESULTS
|
| - _TEST_RECEIVED_EMAIL_RESULTS = results
|
| -
|
| -
|
| -def _MockSendMail(**kwargs):
|
| - global _TEST_RECEIVED_EMAIL
|
| - _TEST_RECEIVED_EMAIL = kwargs
|
| -
|
| -
|
| # In this class, we patch apiclient.discovery.build so as to not make network
|
| # requests, which are normally made when the IssueTrackerService is initialized.
|
| @mock.patch('apiclient.discovery.build', mock.MagicMock())
|
| @@ -501,80 +175,67 @@ class UpdateBugWithResultsTest(testing_common.TestCase):
|
| server_url='https://test-rietveld.appspot.com',
|
| internal_server_url='https://test-rietveld.appspot.com').put()
|
|
|
| + def _AddTryJob(self, bug_id, status, bot, **kwargs):
|
| + job = try_job.TryJob(bug_id=bug_id, status=status, bot=bot, **kwargs)
|
| + job.put()
|
| + bug_data.Bug(id=bug_id).put()
|
| + return job
|
| +
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results.buildbucket_service, 'GetJobStatus',
|
| - _MockGetJobStatus)
|
| def testGet(self):
|
| - # Put succeeded, failed, and not yet finished jobs in the datastore.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - try_job.TryJob(
|
| - bug_id=54321, rietveld_issue_id=302304, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - try_job.TryJob(
|
| - bug_id=99999, rietveld_issue_id=100001, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - try_job.TryJob(
|
| - bug_id=77777, buildbucket_job_id='1234567', use_buildbucket=True,
|
| - status='started', bot='win_perf').put()
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| - bug_data.Bug(id=54321).put()
|
| - bug_data.Bug(id=99999).put()
|
| - bug_data.Bug(id=77777).put()
|
| + # Put succeeded, failed, staled, and not yet finished jobs in the
|
| + # datastore.
|
| + self._AddTryJob(11111, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
| + staled_timestamp = (datetime.datetime.now() -
|
| + update_bug_with_results._STALE_TRYJOB_DELTA)
|
| + self._AddTryJob(22222, 'started', 'win_perf',
|
| + last_ran_timestamp=staled_timestamp)
|
| + self._AddTryJob(33333, 'failed', 'win_perf')
|
| + self._AddTryJob(44444, 'started', 'win_perf')
|
|
|
| self.testapp.get('/update_bug_with_results')
|
| pending_jobs = try_job.TryJob.query().fetch()
|
| - # Expects a failed and not yet finished bisect job to be in datastore.
|
| - self.assertEqual(3, len(pending_jobs))
|
| - self.assertEqual(54321, pending_jobs[0].bug_id)
|
| - self.assertEqual('failed', pending_jobs[0].status)
|
| - self.assertEqual(99999, pending_jobs[1].bug_id)
|
| - self.assertEqual(77777, pending_jobs[2].bug_id)
|
| - self.assertEqual('started', pending_jobs[1].status)
|
| - self.assertEqual('started', pending_jobs[2].status)
|
| - self.assertEqual('bisect', pending_jobs[0].job_type)
|
| - self.assertEqual('bisect', pending_jobs[1].job_type)
|
| - self.assertEqual('bisect', pending_jobs[2].job_type)
|
| + # Expects no jobs to be deleted.
|
| + self.assertEqual(4, len(pending_jobs))
|
| + self.assertEqual(11111, pending_jobs[0].bug_id)
|
| + self.assertEqual('completed', pending_jobs[0].status)
|
| + self.assertEqual(22222, pending_jobs[1].bug_id)
|
| + self.assertEqual('staled', pending_jobs[1].status)
|
| + self.assertEqual(33333, pending_jobs[2].bug_id)
|
| + self.assertEqual('failed', pending_jobs[2].status)
|
| + self.assertEqual(44444, pending_jobs[3].bug_id)
|
| + self.assertEqual('started', pending_jobs[3].status)
|
|
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| mock.MagicMock())
|
| def testCreateTryJob_WithoutExistingBug(self):
|
| # Put succeeded job in the datastore.
|
| try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| + bug_id=12345, status='started', bot='win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON).put()
|
|
|
| self.testapp.get('/update_bug_with_results')
|
| pending_jobs = try_job.TryJob.query().fetch()
|
|
|
| # Expects job to finish.
|
| - self.assertEqual(0, len(pending_jobs))
|
| + self.assertEqual(1, len(pending_jobs))
|
| + self.assertEqual(12345, pending_jobs[0].bug_id)
|
| + self.assertEqual('completed', pending_jobs[0].status)
|
|
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment', mock.MagicMock(return_value=False))
|
| @mock.patch('logging.error')
|
| @@ -582,15 +243,10 @@ class UpdateBugWithResultsTest(testing_common.TestCase):
|
| # Put a successful job and a failed job with partial results.
|
| # Note that AddBugComment is mocked to always returns false, which
|
| # simulates failing to post results to the issue tracker for all bugs.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - try_job.TryJob(
|
| - bug_id=54321, rietveld_issue_id=200039, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - bug_data.Bug(id=12345).put()
|
| - bug_data.Bug(id=54321).put()
|
| -
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
| + self._AddTryJob(54321, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
| self.testapp.get('/update_bug_with_results')
|
|
|
| # Two errors should be logged.
|
| @@ -606,304 +262,73 @@ class UpdateBugWithResultsTest(testing_common.TestCase):
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_BisectJobWithPartialResults(self, mock_update_bug):
|
| - # Put failed job in the datastore.
|
| - try_job.TryJob(
|
| - bug_id=54321, rietveld_issue_id=200039, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - # Create bug.
|
| - bug_data.Bug(id=54321).put()
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(1, len(pending_jobs))
|
| - self.assertEqual('failed', pending_jobs[0].status)
|
| - mock_update_bug.assert_called_once_with(
|
| - 54321, _EXPECTED_BISECT_LOG_PARTIAL_RESULT, labels=None)
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment')
|
| - def testGet_BisectCulpritHasMultipleAuthors_NoneCCd(self, mock_update_bug):
|
| - # When a bisect finds multiple culprits for a perf regression,
|
| - # owners of CLs shouldn't be cc'ed on issue update.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200035, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - bug_data.Bug(id=12345).put()
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - mock_update_bug.assert_called_once_with(
|
| - mock.ANY, mock.ANY, cc_list=[], merge_issue=None, labels=None,
|
| - owner=None)
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_MultipleCulpritsSameAuthor_AssignsAuthor(self, mock_update_bug):
|
| - # When a bisect finds multiple culprits by same Author for a perf
|
| - # regression, owner of CLs should be cc'ed.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200036, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - bug_data.Bug(id=12345).put()
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - mock_update_bug.assert_called_once_with(
|
| - mock.ANY, mock.ANY,
|
| - cc_list=['sullivan@google.com', 'prasadv@google.com'],
|
| - merge_issue=None, labels=None, owner='sullivan@google.com')
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_BisectCulpritHasSingleAuthor_AssignsAuthor(self, mock_update_bug):
|
| - # When a bisect finds a single culprit for a perf regression,
|
| + def testGet_BisectCulpritHasAuthor_AssignsAuthor(self, mock_update_bug):
|
| + # When a bisect has a culprit for a perf regression,
|
| # author and reviewer of the CL should be cc'ed on issue update.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
|
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| self.testapp.get('/update_bug_with_results')
|
| mock_update_bug.assert_called_once_with(
|
| mock.ANY, mock.ANY,
|
| - cc_list=['sullivan@google.com', 'prasadv@google.com'],
|
| - merge_issue=None, labels=None, owner='sullivan@google.com')
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| -
|
| - def testBeautifyContent(self):
|
| - # Remove buildbot annotations (@@@), leading and trailing spaces from bisect
|
| - # results log.
|
| - actual_output = update_bug_with_results._BeautifyContent(
|
| - _BISECT_LOG_SINGLE_OWNER)
|
| - self.assertNotIn('@@@', actual_output)
|
| - for line in actual_output.split('\n'):
|
| - self.assertFalse(line.startswith(' '))
|
| - self.assertFalse(line.endswith(' '))
|
| - self.assertEqual(_EXPECTED_BISECT_LOG_SINGLE_OWNER, actual_output)
|
| + cc_list=['author@email.com', 'prasadv@google.com'],
|
| + merge_issue=None, labels=None, owner='author@email.com')
|
|
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment')
|
| def testGet_FailedRevisionResponse(self, mock_add_bug):
|
| - # When a Rietveld CL link fails to respond, only update CL owner in CC list.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200038, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| + # When a Rietveld CL link fails to respond, only update CL owner in CC
|
| + # list.
|
| + sample_bisect_results = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
|
| + sample_bisect_results['revisions_links'] = [
|
| + 'http://src.chromium.org/viewvc/chrome?view=revision&revision=20799']
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=sample_bisect_results)
|
|
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| self.testapp.get('/update_bug_with_results')
|
| mock_add_bug.assert_called_once_with(mock.ANY,
|
| mock.ANY,
|
| - cc_list=['sullivan@google.com'],
|
| + cc_list=['author@email.com',
|
| + 'prasadv@google.com'],
|
| merge_issue=None,
|
| labels=None,
|
| - owner='sullivan@google.com')
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| + owner='author@email.com')
|
|
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_MergesBugIntoExistingBug(self, mock_update_bug):
|
| - # When there exists a bug with the same revision (commit hash),
|
| - # mark bug as duplicate and merge current issue into that.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - try_job.TryJob(
|
| - bug_id=54321, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| -
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| - bug_data.Bug(id=54321).put()
|
| - self.testapp.get('/update_bug_with_results')
|
| - # Owners of CLs are not cc'ed for duplicate bugs and the issue should be
|
| - # marked as duplicate.
|
| - mock_update_bug.assert_called_with(mock.ANY,
|
| - mock.ANY,
|
| - cc_list=[],
|
| - merge_issue='12345',
|
| - labels=None,
|
| - owner=None)
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| - # Add anomalies.
|
| - test_keys = map(utils.TestKey, [
|
| - 'ChromiumGPU/linux-release/scrolling-benchmark/first_paint',
|
| - 'ChromiumGPU/linux-release/scrolling-benchmark/mean_frame_time'])
|
| - anomaly.Anomaly(
|
| - start_revision=9990, end_revision=9997, test=test_keys[0],
|
| - median_before_anomaly=100, median_after_anomaly=200,
|
| - sheriff=None, bug_id=12345).put()
|
| - anomaly.Anomaly(
|
| - start_revision=9990, end_revision=9996, test=test_keys[0],
|
| - median_before_anomaly=100, median_after_anomaly=200,
|
| - sheriff=None, bug_id=54321).put()
|
| - # Map anomalies to base(dest_bug_id) bug.
|
| - update_bug_with_results._MapAnomaliesToMergeIntoBug(
|
| - dest_bug_id=12345, source_bug_id=54321)
|
| - anomalies = anomaly.Anomaly.query(
|
| - anomaly.Anomaly.bug_id == int(54321)).fetch()
|
| - self.assertEqual(0, len(anomalies))
|
| -
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment', mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Status: Positive\n'
|
| - 'Commit : abcd123\n'
|
| - 'Author : culprit@chromium.org\n'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| def testGet_PositiveResult_StoresCommitHash(self):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - self.testapp.get('/update_bug_with_results')
|
| - self.assertEqual('12345', layered_cache.GetExternal('commit_hash_abcd123'))
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
|
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment', mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Status: Negative\n'
|
| - 'Commit : a121212\n'
|
| - 'Author : culprit@chromium.org\n'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| - def testGet_NegativeResult_DoesNotStoreCommitHash(self):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| self.testapp.get('/update_bug_with_results')
|
| - self.assertIsNone(layered_cache.GetExternal('commit_hash_a121212'))
|
| + self.assertEqual('12345', layered_cache.GetExternal('commit_hash_123'))
|
|
|
| + @mock.patch(
|
| + 'google.appengine.api.urlfetch.fetch',
|
| + mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment', mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Status: Positive\n'
|
| - 'Commit : a12\n'
|
| - 'Commit : b23\n'
|
| - 'Author : culprit@chromium.org\n'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| - def testGet_MultipleCommits_DoesNotStoreCommitHash(self):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| + def testGet_NegativeResult_DoesNotStoreCommitHash(self):
|
| + sample_bisect_results = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
|
| + sample_bisect_results['culprit_data'] = None
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=sample_bisect_results)
|
| self.testapp.get('/update_bug_with_results')
|
| - self.assertIsNone(layered_cache.GetExternal('commit_hash_a12b23'))
|
|
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Status: Positive\n'
|
| - 'Commit : a121212\n'
|
| - 'Author : culprit@chromium.org\n'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_PositiveResult_CCsAuthor(self, mock_update_bug):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - bug_data.Bug(id=12345).put()
|
| - self.testapp.get('/update_bug_with_results')
|
| - mock_update_bug.assert_called_with(
|
| - 12345, mock.ANY, cc_list=['culprit@chromium.org'],
|
| - merge_issue=None, labels=None, owner='culprit@chromium.org')
|
| -
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Status: Negative\n'
|
| - 'Commit : a121212\n'
|
| - 'Author : culprit@chromium.org\n'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_NegativeResult_DoesNotCCAuthor(self, mock_update_bug):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - bug_data.Bug(id=12345).put()
|
| - self.testapp.get('/update_bug_with_results')
|
| - mock_update_bug.assert_called_with(
|
| - 12345, mock.ANY, cc_list=[], merge_issue=None, labels=None, owner=None)
|
| + caches = layered_cache.CachedPickledString.query().fetch()
|
| + # Only 1 cache for bisect stats.
|
| + self.assertEqual(1, len(caches))
|
|
|
| def testMapAnomaliesToMergeIntoBug(self):
|
| # Add anomalies.
|
| @@ -929,372 +354,52 @@ class UpdateBugWithResultsTest(testing_common.TestCase):
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(update_bug_with_results, '_LogBisectInfraFailure')
|
| - def testCheckBisectBotForInfraFailure_BotFailure(
|
| - self, log_bisect_failure_mock):
|
| - bug_id = 516
|
| - build_data = {
|
| - 'steps': [{'name': 'A', 'results': [0]},
|
| - {'name': 'B', 'results': [2]}],
|
| - 'times': [1411501756, 1411545237],
|
| - }
|
| - build_url = 'http://build.chromium.org/builders/516'
|
| - update_bug_with_results._CheckBisectBotForInfraFailure(
|
| - bug_id, build_data, build_url)
|
| - log_bisect_failure_mock.assert_called_with(
|
| - bug_id, 'Bot failure.', mock.ANY)
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(update_bug_with_results, '_LogBisectInfraFailure')
|
| - def testCheckBisectBotForInfraFailure_BuildFailure(
|
| - self, log_bisect_failure_mock):
|
| - bug_id = 516
|
| - build_data = {
|
| - 'steps': [{'name': 'A', 'results': [0]},
|
| - {'name': 'slave_steps', 'results': [2]}],
|
| - 'times': [1411500000, 1411501000],
|
| - }
|
| - build_url = 'http://build.chromium.org/builders/516'
|
| - update_bug_with_results._CheckBisectBotForInfraFailure(
|
| - bug_id, build_data, build_url)
|
| - log_bisect_failure_mock.assert_called_with(
|
| - bug_id, 'Build failure.', mock.ANY)
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| - 'AddBugComment')
|
| - def testGet_BotInfoInBisectResults(self, mock_update_bug):
|
| - # When a bisect finds multiple culprits by same Author for a perf
|
| - # regression, owner of CLs should be cc'ed.
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| -
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| - self.testapp.get('/update_bug_with_results')
|
| - mock_update_bug.assert_called_once_with(
|
| - 12345,
|
| - _EXPECTED_BISECT_RESULTS_ON_BUG,
|
| - cc_list=['sullivan@google.com', 'prasadv@google.com'],
|
| - merge_issue=None,
|
| - labels=None,
|
| - owner='sullivan@google.com')
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_SendPerfTryJobEmail',
|
| - mock.MagicMock(side_effect=_MockSendPerfTryJobEmail))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| - mock.MagicMock())
|
| - def testGet_PerfTryJob(self):
|
| - try_job.TryJob(
|
| - rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf', email='just@atestemail.com',
|
| - job_type='perf-try', config=_PERF_TEST_CONFIG).put()
|
| - global _TEST_RECEIVED_EMAIL_RESULTS
|
| - _TEST_RECEIVED_EMAIL_RESULTS = None
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - results = _TEST_RECEIVED_EMAIL_RESULTS
|
| - self.assertEqual('Completed', results['status'])
|
| - self.assertEqual(2, len(results['profiler_results']))
|
| - self.assertEqual(_PERF_LOG_EXPECTED_HTML_LINK,
|
| - results['html_results'])
|
| - self.assertEqual(_PERF_LOG_EXPECTED_TITLE_1,
|
| - results['profiler_results'][0][0])
|
| - self.assertEqual(_PERF_LOG_EXPECTED_PROFILER_LINK1,
|
| - results['profiler_results'][0][1])
|
| - self.assertEqual(_PERF_LOG_EXPECTED_TITLE_2,
|
| - results['profiler_results'][1][0])
|
| - self.assertEqual(_PERF_LOG_EXPECTED_PROFILER_LINK2,
|
| - results['profiler_results'][1][1])
|
| - self.assertEqual('win_perf_bisect', results['bisect_bot'])
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_SendPerfTryJobEmail',
|
| - mock.MagicMock(side_effect=_MockSendPerfTryJobEmail))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| - mock.MagicMock())
|
| - def testGet_PerfTryJobWithInvalidOutput_EmailResultsAreEmpty(self):
|
| - try_job.TryJob(
|
| - rietveld_issue_id=200035, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf', email='just@atestemail.com',
|
| - job_type='perf-try', config=_PERF_TEST_CONFIG).put()
|
| - global _TEST_RECEIVED_EMAIL_RESULTS
|
| - _TEST_RECEIVED_EMAIL_RESULTS = None
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - results = _TEST_RECEIVED_EMAIL_RESULTS
|
| - self.assertEqual('Completed', results['status'])
|
| - self.assertEqual(0, len(results['profiler_results']))
|
| - self.assertEqual('', results['html_results'])
|
| - self.assertEqual('win_perf_bisect', results['bisect_bot'])
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch(
|
| - 'google.appengine.api.mail.send_mail',
|
| - mock.MagicMock(side_effect=_MockSendMail))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| - mock.MagicMock())
|
| - def testGet_CreatePerfSuccessEmail(self):
|
| - try_job.TryJob(
|
| - rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf', email='just@atestemail.com',
|
| - job_type='perf-try', config=_PERF_TEST_CONFIG).put()
|
| - global _TEST_RECEIVED_EMAIL
|
| - _TEST_RECEIVED_EMAIL = {}
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| -
|
| - self.assertIn('<a href="http://build.chromium.org/508">'
|
| - 'http://build.chromium.org/508</a>.',
|
| - _TEST_RECEIVED_EMAIL.get('html'))
|
| - self.assertIn('With Patch', _TEST_RECEIVED_EMAIL.get('body'))
|
| - self.assertIn('Without Patch', _TEST_RECEIVED_EMAIL.get('body'))
|
| - self.assertIn('just@atestemail.com',
|
| - _TEST_RECEIVED_EMAIL.get('to'))
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch(
|
| - 'google.appengine.api.mail.send_mail',
|
| - mock.MagicMock(side_effect=_MockSendMail))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| - mock.MagicMock())
|
| - def testGet_CreatePerfFailureEmail(self):
|
| - try_job.TryJob(
|
| - rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf', email='just@atestemail.com',
|
| - job_type='perf-try').put()
|
| -
|
| - global _TEST_RECEIVED_EMAIL
|
| - _TEST_RECEIVED_EMAIL = {}
|
| -
|
| + update_bug_with_results.email_template,
|
| + 'GetPerfTryJobEmailReport', mock.MagicMock(return_value=None))
|
| + def testSendPerfTryJobEmail_EmptyEmailReport_DontSendEmail(self):
|
| + self._AddTryJob(12345, 'started', 'win_perf', job_type='perf-try',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON)
|
| self.testapp.get('/update_bug_with_results')
|
| -
|
| - self.assertIn('Perf Try Job FAILURE\n<br>',
|
| - _TEST_RECEIVED_EMAIL.get('html'))
|
| - self.assertIn('Perf Try Job FAILURE\n\n',
|
| - _TEST_RECEIVED_EMAIL.get('body'))
|
| - self.assertIn('just@atestemail.com',
|
| - _TEST_RECEIVED_EMAIL.get('to'))
|
| + messages = self.mail_stub.get_sent_messages()
|
| + self.assertEqual(0, len(messages))
|
|
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service.IssueTrackerService,
|
| 'AddBugComment')
|
| def testGet_InternalOnlyTryJob_AddsInternalOnlyBugLabel(
|
| self, mock_update_bug):
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf', internal_only=True).put()
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON,
|
| + internal_only=True)
|
|
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| self.testapp.get('/update_bug_with_results')
|
| mock_update_bug.assert_called_once_with(
|
| mock.ANY, mock.ANY,
|
| cc_list=mock.ANY,
|
| merge_issue=None, labels=['Restrict-View-Google'], owner=mock.ANY)
|
|
|
| - def testValidateAndConvertBuildbucketResponse_NoResults(self):
|
| - buildbucket_response_scheduled = r"""{
|
| - "build": {
|
| - "status": "SCHEDULED",
|
| - "id": "9043191319901995952"
|
| - }
|
| - }"""
|
| - with self.assertRaises(update_bug_with_results.UnexpectedJsonError):
|
| - update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - json.loads(buildbucket_response_scheduled))
|
| -
|
| - def testValidateAndConvertBuildbucketResponse_Failed(self):
|
| - buildbucket_response_failed = r"""{
|
| - "build": {
|
| - "status": "COMPLETED",
|
| - "url": "http://build.chromium.org/linux_perf_bisector/builds/41",
|
| - "failure_reason": "BUILD_FAILURE",
|
| - "result": "FAILURE",
|
| - "id": "9043547105089652704"
|
| - }
|
| - }"""
|
| - converted_response = (
|
| - update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - json.loads(buildbucket_response_failed)))
|
| - self.assertIn('http', converted_response['url'])
|
| - self.assertEqual(converted_response['result'],
|
| - update_bug_with_results.FAILURE)
|
| -
|
| - def testValidateAndConvertBuildbucketResponse_Success(self):
|
| - buildbucket_response_success = r"""{
|
| - "build": {
|
| - "status": "COMPLETED",
|
| - "url": "http://build.chromium.org/linux_perf_bisector/builds/47",
|
| - "id": "9043278384371361584",
|
| - "result": "SUCCESS"
|
| - }
|
| - }"""
|
| - converted_response = (
|
| - update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - json.loads(buildbucket_response_success)))
|
| - self.assertIn('http', converted_response['url'])
|
| - self.assertEqual(converted_response['result'],
|
| - update_bug_with_results.SUCCESS)
|
| -
|
| - def testValidateAndConvertBuildbucketResponse_Canceled(self):
|
| - buildbucket_response_canceled = r"""{
|
| - "build": {
|
| - "status": "COMPLETED",
|
| - "cancellation_reason": "TIMEOUT",
|
| - "id": "9043278384371361584",
|
| - "result": "CANCELED"
|
| - }
|
| - }"""
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(1, len(pending_jobs))
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| - with self.assertRaises(update_bug_with_results.UnexpectedJsonError):
|
| - update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - json.loads(buildbucket_response_canceled), pending_jobs[0])
|
| - pending_jobs = try_job.TryJob.query(
|
| - try_job.TryJob.status == 'failed').fetch()
|
| - self.assertEqual(1, len(pending_jobs))
|
| -
|
| - def testValidateAndConvertBuildbucketResponse_InvalidConfig(self):
|
| - buildbucket_response_canceled = r"""{
|
| - "build": {
|
| - "status": "COMPLETED",
|
| - "failure_reason": "INVALID_BUILD_DEFINITION",
|
| - "id": "9043278384371361584",
|
| - "result": "FAILURE"
|
| - }
|
| - }"""
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200037, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf').put()
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(1, len(pending_jobs))
|
| - # Create bug.
|
| - bug_data.Bug(id=12345).put()
|
| - with self.assertRaises(update_bug_with_results.UnexpectedJsonError):
|
| - update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - json.loads(buildbucket_response_canceled), pending_jobs[0])
|
| - pending_jobs = try_job.TryJob.query().fetch()
|
| - self.assertEqual(0, len(pending_jobs))
|
| -
|
| - @mock.patch('logging.error')
|
| - def testValidateAndConvertBuildbucketResponse_NoTesterInConfig(
|
| - self, mock_logging_error):
|
| - job_info = {
|
| - 'build': {
|
| - 'status': 'foo',
|
| - 'url': 'www.baz.com',
|
| - 'result': 'bar',
|
| - }
|
| - }
|
| - result = update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - job_info)
|
| - self.assertEqual('Unknown', result['builder'])
|
| - self.assertEqual(1, mock_logging_error.call_count)
|
| -
|
| - def testValidateAndConvertBuildbucketResponse_TesterInConfig(self):
|
| - job_info = {
|
| - 'build': {
|
| - 'status': 'foo',
|
| - 'url': 'www.baz.com',
|
| - 'result': 'bar',
|
| - 'result_details_json': json.dumps({
|
| - 'properties': {
|
| - 'bisect_config': {'recipe_tester_name': 'my_perf_bisect'}
|
| - }
|
| - })
|
| - }
|
| - }
|
| - result = update_bug_with_results._ValidateAndConvertBuildbucketResponse(
|
| - job_info)
|
| - self.assertEqual('my_perf_bisect', result['builder'])
|
| -
|
| @mock.patch(
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('===== BISECT JOB RESULTS =====\n'
|
| - 'Status: Positive\n'
|
| - 'Commit : 2a1781d64d'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| def testFYI_Send_No_Email_On_Success(self):
|
| stored_object.Set(
|
| bisect_fyi._BISECT_FYI_CONFIGS_KEY,
|
| bisect_fyi_test.TEST_FYI_CONFIGS)
|
| test_config = bisect_fyi_test.TEST_FYI_CONFIGS['positive_culprit']
|
| bisect_config = test_config.get('bisect_config')
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf',
|
| - job_name='positive_culprit',
|
| - job_type='bisect-fyi',
|
| - config=utils.BisectConfigPythonString(bisect_config)).put()
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=_SAMPLE_BISECT_RESULTS_JSON,
|
| + internal_only=True,
|
| + config=utils.BisectConfigPythonString(bisect_config),
|
| + job_type='bisect-fyi',
|
| + job_name='positive_culprit',
|
| + email='chris@email.com')
|
|
|
| self.testapp.get('/update_bug_with_results')
|
| messages = self.mail_stub.get_sent_messages()
|
| @@ -1304,93 +409,30 @@ class UpdateBugWithResultsTest(testing_common.TestCase):
|
| 'google.appengine.api.urlfetch.fetch',
|
| mock.MagicMock(side_effect=_MockFetch))
|
| @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch(
|
| - 'google.appengine.api.mail.send_mail',
|
| - mock.MagicMock(side_effect=_MockSendMail))
|
| + update_bug_with_results.bisect_fyi, 'IsBugUpdated',
|
| + mock.MagicMock(return_value=True))
|
| @mock.patch.object(
|
| update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('===== BISECT JOB RESULTS =====\n'
|
| - 'Status: Positive\n'
|
| - 'Commit : a121212'),
|
| - 'status': 'Completed',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| - def testFYI_Expected_Results_Mismatch_SendEmail(self):
|
| - stored_object.Set(
|
| - bisect_fyi._BISECT_FYI_CONFIGS_KEY,
|
| - bisect_fyi_test.TEST_FYI_CONFIGS)
|
| - test_config = bisect_fyi_test.TEST_FYI_CONFIGS['positive_culprit']
|
| - bisect_config = test_config.get('bisect_config')
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf',
|
| - job_name='positive_culprit',
|
| - job_type='bisect-fyi',
|
| - config=utils.BisectConfigPythonString(bisect_config)).put()
|
| -
|
| - global _TEST_RECEIVED_EMAIL
|
| - _TEST_RECEIVED_EMAIL = None
|
| -
|
| - self.testapp.get('/update_bug_with_results')
|
| - self.assertIn('<font color="red"><b>Bisect FYI Try Job Failed</b></font>',
|
| - _TEST_RECEIVED_EMAIL.get('html'))
|
| - self.assertIn('Bisect FYI Try Job Failed\n\n',
|
| - _TEST_RECEIVED_EMAIL.get('body'))
|
| - self.assertIn('auto-bisect-team@google.com',
|
| - _TEST_RECEIVED_EMAIL.get('to'))
|
| -
|
| - @mock.patch(
|
| - 'google.appengine.api.urlfetch.fetch',
|
| - mock.MagicMock(side_effect=_MockFetch))
|
| - @mock.patch.object(
|
| - update_bug_with_results.rietveld_service.RietveldService, 'MakeRequest',
|
| - mock.MagicMock(side_effect=_MockMakeRequest))
|
| - @mock.patch(
|
| - 'google.appengine.api.mail.send_mail',
|
| - mock.MagicMock(side_effect=_MockSendMail))
|
| - @mock.patch.object(
|
| - update_bug_with_results.issue_tracker_service, 'IssueTrackerService',
|
| - mock.MagicMock())
|
| - @mock.patch.object(
|
| - update_bug_with_results, '_GetBisectResults',
|
| - mock.MagicMock(return_value={
|
| - 'results': ('Failed to produce build.'),
|
| - 'status': 'Failure',
|
| - 'bisect_bot': 'bar',
|
| - 'issue_url': 'bar',
|
| - 'buildbot_log_url': 'bar',
|
| - }))
|
| def testFYI_Failed_Job_SendEmail(self):
|
| stored_object.Set(
|
| bisect_fyi._BISECT_FYI_CONFIGS_KEY,
|
| bisect_fyi_test.TEST_FYI_CONFIGS)
|
| test_config = bisect_fyi_test.TEST_FYI_CONFIGS['positive_culprit']
|
| bisect_config = test_config.get('bisect_config')
|
| - try_job.TryJob(
|
| - bug_id=12345, rietveld_issue_id=200034, rietveld_patchset_id=1,
|
| - status='started', bot='win_perf',
|
| - job_name='positive_culprit',
|
| - job_type='bisect-fyi',
|
| - config=utils.BisectConfigPythonString(bisect_config)).put()
|
| -
|
| - global _TEST_RECEIVED_EMAIL
|
| - _TEST_RECEIVED_EMAIL = None
|
| + sample_bisect_results = copy.deepcopy(_SAMPLE_BISECT_RESULTS_JSON)
|
| + sample_bisect_results['status'] = 'failed'
|
| + self._AddTryJob(12345, 'started', 'win_perf',
|
| + results_data=sample_bisect_results,
|
| + internal_only=True,
|
| + config=utils.BisectConfigPythonString(bisect_config),
|
| + job_type='bisect-fyi',
|
| + job_name='positive_culprit',
|
| + email='chris@email.com')
|
|
|
| self.testapp.get('/update_bug_with_results')
|
| - self.assertIn('<font color="red"><b>Bisect FYI Try Job Failed</b></font>',
|
| - _TEST_RECEIVED_EMAIL.get('html'))
|
| - self.assertIn('Bisect FYI Try Job Failed\n\n',
|
| - _TEST_RECEIVED_EMAIL.get('body'))
|
| - self.assertIn('auto-bisect-team@google.com',
|
| - _TEST_RECEIVED_EMAIL.get('to'))
|
| + messages = self.mail_stub.get_sent_messages()
|
| + self.assertEqual(1, len(messages))
|
|
|
|
|
| if __name__ == '__main__':
|
|
|