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__': |