| OLD | NEW |
| (Empty) |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 import json | |
| 6 | |
| 7 from common.git_repository import GitRepository | |
| 8 from common.pipeline_wrapper import BasePipeline | |
| 9 from common.pipeline_wrapper import pipeline_handlers | |
| 10 from common.waterfall import buildbucket_client | |
| 11 from model import analysis_status | |
| 12 from model import result_status | |
| 13 from model.wf_analysis import WfAnalysis | |
| 14 from model.wf_try_job import WfTryJob | |
| 15 from waterfall import send_notification_for_culprit_pipeline | |
| 16 from waterfall.test import wf_testcase | |
| 17 from waterfall.try_job_pipeline import TryJobPipeline | |
| 18 from waterfall.try_job_type import TryJobType | |
| 19 | |
| 20 | |
| 21 class TryJobPipelineTest(wf_testcase.WaterfallTestCase): | |
| 22 app_module = pipeline_handlers._APP | |
| 23 | |
| 24 def _Mock_TriggerTryJobs(self, responses): | |
| 25 def MockedTriggerTryJobs(*_): | |
| 26 try_job_results = [] | |
| 27 for response in responses: | |
| 28 if response.get('error'): # pragma: no cover | |
| 29 try_job_results.append(( | |
| 30 buildbucket_client.BuildbucketError(response['error']), None)) | |
| 31 else: | |
| 32 try_job_results.append(( | |
| 33 None, buildbucket_client.BuildbucketBuild(response['build']))) | |
| 34 return try_job_results | |
| 35 self.mock(buildbucket_client, 'TriggerTryJobs', MockedTriggerTryJobs) | |
| 36 | |
| 37 def _Mock_GetTryJobs(self, build_id): | |
| 38 def MockedGetTryJobs(*_): | |
| 39 data = { | |
| 40 '1': { | |
| 41 'build': { | |
| 42 'id': '1', | |
| 43 'url': 'url', | |
| 44 'status': 'COMPLETED', | |
| 45 'result_details_json': json.dumps({ | |
| 46 'properties': { | |
| 47 'report': { | |
| 48 'result': { | |
| 49 'rev1': 'passed', | |
| 50 'rev2': 'failed' | |
| 51 }, | |
| 52 'metadata': { | |
| 53 'regression_range_size': 2 | |
| 54 } | |
| 55 } | |
| 56 } | |
| 57 }) | |
| 58 } | |
| 59 }, | |
| 60 '3': { | |
| 61 'error': { | |
| 62 'reason': 'BUILD_NOT_FOUND', | |
| 63 'message': 'message', | |
| 64 } | |
| 65 } | |
| 66 } | |
| 67 try_job_results = [] | |
| 68 build_error = data.get(build_id) | |
| 69 if build_error.get('error'): # pragma: no cover | |
| 70 try_job_results.append(( | |
| 71 buildbucket_client.BuildbucketError(build_error['error']), None)) | |
| 72 else: | |
| 73 try_job_results.append(( | |
| 74 None, buildbucket_client.BuildbucketBuild(build_error['build']))) | |
| 75 return try_job_results | |
| 76 self.mock(buildbucket_client, 'GetTryJobs', MockedGetTryJobs) | |
| 77 | |
| 78 def _Mock_GetChangeLog(self, revision): | |
| 79 def MockedGetChangeLog(*_): | |
| 80 class MockedChangeLog(object): | |
| 81 | |
| 82 def __init__(self, commit_position, code_review_url): | |
| 83 self.commit_position = commit_position | |
| 84 self.code_review_url = code_review_url | |
| 85 | |
| 86 mock_change_logs = {} | |
| 87 mock_change_logs['rev2'] = MockedChangeLog('2', 'url_2') | |
| 88 return mock_change_logs.get(revision) | |
| 89 self.mock(GitRepository, 'GetChangeLog', MockedGetChangeLog) | |
| 90 | |
| 91 def _Mock_SendNotificationForCulpritPipeline(self): | |
| 92 class Mocked_Pipeline(BasePipeline): | |
| 93 def run(self, *args, **kwargs): # unused arg - pylint: disable=W0612 | |
| 94 pass | |
| 95 self.mock(send_notification_for_culprit_pipeline, | |
| 96 'SendNotificationForCulpritPipeline', Mocked_Pipeline) | |
| 97 | |
| 98 def testSuccessfullyScheduleNewTryJobForCompile(self): | |
| 99 master_name = 'm' | |
| 100 builder_name = 'b' | |
| 101 build_number = 1 | |
| 102 | |
| 103 responses = [ | |
| 104 { | |
| 105 'build': { | |
| 106 'id': '1', | |
| 107 'url': 'url', | |
| 108 'status': 'SCHEDULED', | |
| 109 } | |
| 110 } | |
| 111 ] | |
| 112 | |
| 113 self._Mock_TriggerTryJobs(responses) | |
| 114 self._Mock_GetTryJobs('1') | |
| 115 self._Mock_GetChangeLog('rev2') | |
| 116 self._Mock_SendNotificationForCulpritPipeline() | |
| 117 | |
| 118 WfTryJob.Create(master_name, builder_name, build_number).put() | |
| 119 analysis = WfAnalysis.Create(master_name, builder_name, build_number) | |
| 120 analysis.put() | |
| 121 | |
| 122 root_pipeline = TryJobPipeline( | |
| 123 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], | |
| 124 TryJobType.COMPILE, []) | |
| 125 root_pipeline.start() | |
| 126 self.execute_queued_tasks() | |
| 127 | |
| 128 try_job = WfTryJob.Get(master_name, builder_name, build_number) | |
| 129 expected_suspected_cl = { | |
| 130 'revision': 'rev2', | |
| 131 'commit_position': '2', | |
| 132 'url': 'url_2', | |
| 133 'repo_name': 'chromium' | |
| 134 } | |
| 135 | |
| 136 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | |
| 137 expected_try_job_results = [ | |
| 138 { | |
| 139 'report': { | |
| 140 'result': { | |
| 141 'rev1': 'passed', | |
| 142 'rev2': 'failed' | |
| 143 }, | |
| 144 'metadata': { | |
| 145 'regression_range_size': 2 | |
| 146 } | |
| 147 }, | |
| 148 'url': 'url', | |
| 149 'try_job_id': '1', | |
| 150 'culprit': { | |
| 151 'compile': expected_suspected_cl | |
| 152 } | |
| 153 } | |
| 154 ] | |
| 155 self.assertEqual(expected_try_job_results, try_job.compile_results) | |
| 156 self.assertEqual(analysis.result_status, | |
| 157 result_status.FOUND_UNTRIAGED) | |
| 158 self.assertEqual(analysis.suspected_cls, | |
| 159 [expected_suspected_cl]) | |
| 160 | |
| 161 def testPipelineAbortedWithTryJobResult(self): | |
| 162 master_name = 'm' | |
| 163 builder_name = 'b' | |
| 164 build_number = 1 | |
| 165 | |
| 166 WfTryJob.Create(master_name, builder_name, build_number).put() | |
| 167 | |
| 168 root_pipeline = TryJobPipeline( | |
| 169 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], | |
| 170 TryJobType.COMPILE, []) | |
| 171 root_pipeline._LogUnexpectedAbort(True) | |
| 172 | |
| 173 try_job = WfTryJob.Get(master_name, builder_name, build_number) | |
| 174 self.assertEqual(analysis_status.ERROR, try_job.status) | |
| 175 | |
| 176 def testPipelineAbortedWithOutTryJobResult(self): | |
| 177 master_name = 'm' | |
| 178 builder_name = 'b' | |
| 179 build_number = 1 | |
| 180 | |
| 181 root_pipeline = TryJobPipeline( | |
| 182 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], | |
| 183 TryJobType.COMPILE, []) | |
| 184 root_pipeline._LogUnexpectedAbort(True) | |
| 185 | |
| 186 try_job = WfTryJob.Get(master_name, builder_name, build_number) | |
| 187 | |
| 188 self.assertIsNone(try_job) | |
| OLD | NEW |