| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import json | 5 import json |
| 6 | 6 |
| 7 from testing_utils import testing | 7 from testing_utils import testing |
| 8 | 8 |
| 9 from common import buildbucket_client | 9 from common import buildbucket_client |
| 10 from common.git_repository import GitRepository |
| 10 from model import wf_analysis_status | 11 from model import wf_analysis_status |
| 11 from model.wf_try_job import WfTryJob | 12 from model.wf_try_job import WfTryJob |
| 12 from pipeline_wrapper import pipeline_handlers | 13 from pipeline_wrapper import pipeline_handlers |
| 13 from waterfall import waterfall_config | 14 from waterfall import waterfall_config |
| 14 from waterfall.try_job_pipeline import TryJobPipeline | 15 from waterfall.try_job_pipeline import TryJobPipeline |
| 15 | 16 |
| 16 | 17 |
| 17 class TryJobPipelineTest(testing.AppengineTestCase): | 18 class TryJobPipelineTest(testing.AppengineTestCase): |
| 18 app_module = pipeline_handlers._APP | 19 app_module = pipeline_handlers._APP |
| 19 | 20 |
| 20 def _Mock_GetTrybotForWaterfallBuilder(self, *_): | 21 def _Mock_GetTrybotForWaterfallBuilder(self, *_): |
| 21 def Mocked_GetTrybotForWaterfallBuilder(*_): | 22 def Mocked_GetTrybotForWaterfallBuilder(*_): |
| 22 return 'linux_chromium_variable', 'master.tryserver.chromium.linux' | 23 return 'linux_chromium_variable', 'master.tryserver.chromium.linux' |
| 23 self.mock(waterfall_config, 'GetTrybotForWaterfallBuilder', | 24 self.mock(waterfall_config, 'GetTrybotForWaterfallBuilder', |
| 24 Mocked_GetTrybotForWaterfallBuilder) | 25 Mocked_GetTrybotForWaterfallBuilder) |
| 25 | 26 |
| 26 def _Mock_TriggerTryJobs(self, responses): | 27 def _Mock_TriggerTryJobs(self, responses): |
| 27 def Mocked_TriggerTryJobs(*_): | 28 def Mocked_TriggerTryJobs(*_): |
| 28 compile_results = [] | 29 try_job_results = [] |
| 29 for response in responses: | 30 for response in responses: |
| 30 if response.get('error'): # pragma: no cover | 31 if response.get('error'): # pragma: no cover |
| 31 compile_results.append(( | 32 try_job_results.append(( |
| 32 buildbucket_client.BuildbucketError(response['error']), None)) | 33 buildbucket_client.BuildbucketError(response['error']), None)) |
| 33 else: | 34 else: |
| 34 compile_results.append(( | 35 try_job_results.append(( |
| 35 None, buildbucket_client.BuildbucketBuild(response['build']))) | 36 None, buildbucket_client.BuildbucketBuild(response['build']))) |
| 36 return compile_results | 37 return try_job_results |
| 37 self.mock(buildbucket_client, 'TriggerTryJobs', Mocked_TriggerTryJobs) | 38 self.mock(buildbucket_client, 'TriggerTryJobs', Mocked_TriggerTryJobs) |
| 38 | 39 |
| 39 def _Mock_GetTryJobs(self, build_id): | 40 def _Mock_GetTryJobs(self, build_id): |
| 40 def Mocked_GetTryJobs(*_): | 41 def Mocked_GetTryJobs(*_): |
| 41 data = { | 42 data = { |
| 42 '1': { | 43 '1': { |
| 43 'build': { | 44 'build': { |
| 44 'id': '1', | 45 'id': '1', |
| 45 'url': 'url', | 46 'url': 'url', |
| 46 'status': 'COMPLETED', | 47 'status': 'COMPLETED', |
| (...skipping 12 matching lines...) Expand all Loading... |
| 59 }) | 60 }) |
| 60 } | 61 } |
| 61 }, | 62 }, |
| 62 '3': { | 63 '3': { |
| 63 'error': { | 64 'error': { |
| 64 'reason': 'BUILD_NOT_FOUND', | 65 'reason': 'BUILD_NOT_FOUND', |
| 65 'message': 'message', | 66 'message': 'message', |
| 66 } | 67 } |
| 67 } | 68 } |
| 68 } | 69 } |
| 69 compile_results = [] | 70 try_job_results = [] |
| 70 build_error = data.get(build_id) | 71 build_error = data.get(build_id) |
| 71 if build_error.get('error'): # pragma: no cover | 72 if build_error.get('error'): # pragma: no cover |
| 72 compile_results.append(( | 73 try_job_results.append(( |
| 73 buildbucket_client.BuildbucketError(build_error['error']), None)) | 74 buildbucket_client.BuildbucketError(build_error['error']), None)) |
| 74 else: | 75 else: |
| 75 compile_results.append(( | 76 try_job_results.append(( |
| 76 None, buildbucket_client.BuildbucketBuild(build_error['build']))) | 77 None, buildbucket_client.BuildbucketBuild(build_error['build']))) |
| 77 return compile_results | 78 return try_job_results |
| 78 self.mock(buildbucket_client, 'GetTryJobs', Mocked_GetTryJobs) | 79 self.mock(buildbucket_client, 'GetTryJobs', Mocked_GetTryJobs) |
| 79 | 80 |
| 81 def _Mock_GetChangeLog(self, revision): |
| 82 def Mocked_GetChangeLog(*_): |
| 83 class MockedChangeLog(object): |
| 84 def __init__(self, commit_position, code_review_url): |
| 85 self.commit_position = commit_position |
| 86 self.code_review_url = code_review_url |
| 87 |
| 88 mock_change_logs = {} |
| 89 mock_change_logs['rev2'] = MockedChangeLog('2', 'url_2') |
| 90 return mock_change_logs.get(revision) |
| 91 self.mock(GitRepository, 'GetChangeLog', Mocked_GetChangeLog) |
| 92 |
| 80 def testSuccessfullyScheduleNewTryJobForCompile(self): | 93 def testSuccessfullyScheduleNewTryJobForCompile(self): |
| 81 master_name = 'm' | 94 master_name = 'm' |
| 82 builder_name = 'b' | 95 builder_name = 'b' |
| 83 build_number = 1 | 96 build_number = 1 |
| 84 good_revision = 'rev1' | |
| 85 bad_revision = 'rev2' | |
| 86 | 97 |
| 87 responses = [ | 98 responses = [ |
| 88 { | 99 { |
| 89 'build': { | 100 'build': { |
| 90 'id': '1', | 101 'id': '1', |
| 91 'url': 'url', | 102 'url': 'url', |
| 92 'status': 'SCHEDULED', | 103 'status': 'SCHEDULED', |
| 93 } | 104 } |
| 94 } | 105 } |
| 95 ] | 106 ] |
| 96 self._Mock_GetTrybotForWaterfallBuilder(master_name, builder_name) | 107 self._Mock_GetTrybotForWaterfallBuilder(master_name, builder_name) |
| 97 self._Mock_TriggerTryJobs(responses) | 108 self._Mock_TriggerTryJobs(responses) |
| 98 self._Mock_GetTryJobs('1') | 109 self._Mock_GetTryJobs('1') |
| 110 self._Mock_GetChangeLog('rev2') |
| 99 | 111 |
| 100 WfTryJob.Create(master_name, builder_name, build_number).put() | 112 WfTryJob.Create(master_name, builder_name, build_number).put() |
| 101 | 113 |
| 102 root_pipeline = TryJobPipeline( | 114 root_pipeline = TryJobPipeline( |
| 103 master_name, builder_name, build_number, good_revision, bad_revision, | 115 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], |
| 104 []) | 116 'compile', []) |
| 105 root_pipeline.start() | 117 root_pipeline.start() |
| 106 self.execute_queued_tasks() | 118 self.execute_queued_tasks() |
| 107 | 119 |
| 108 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 120 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 109 | 121 |
| 110 expected_compile_results = [ | 122 expected_try_job_results = [ |
| 111 { | 123 { |
| 112 'report': { | 124 'report': { |
| 113 'result': { | 125 'result': { |
| 114 'rev1': 'passed', | 126 'rev1': 'passed', |
| 115 'rev2': 'failed' | 127 'rev2': 'failed' |
| 116 }, | 128 }, |
| 117 'metadata': { | 129 'metadata': { |
| 118 'regression_range_size': 2 | 130 'regression_range_size': 2 |
| 119 } | 131 } |
| 120 }, | 132 }, |
| 121 'url': 'url', | 133 'url': 'url', |
| 122 'try_job_id': '1', | 134 'try_job_id': '1', |
| 135 'culprit': { |
| 136 'revision': 'rev2', |
| 137 'commit_position': '2', |
| 138 'review_url': 'url_2' |
| 139 } |
| 123 } | 140 } |
| 124 ] | 141 ] |
| 125 self.assertEqual(expected_compile_results, try_job.compile_results) | 142 self.assertEqual(expected_try_job_results, try_job.compile_results) |
| 126 | 143 |
| 127 def testPipelineAbortedWithTryJobResult(self): | 144 def testPipelineAbortedWithTryJobResult(self): |
| 128 master_name = 'm' | 145 master_name = 'm' |
| 129 builder_name = 'b' | 146 builder_name = 'b' |
| 130 build_number = 1 | 147 build_number = 1 |
| 131 | 148 |
| 132 WfTryJob.Create(master_name, builder_name, build_number).put() | 149 WfTryJob.Create(master_name, builder_name, build_number).put() |
| 133 | 150 |
| 134 root_pipeline = TryJobPipeline( | 151 root_pipeline = TryJobPipeline( |
| 135 master_name, builder_name, build_number, 'rev1', 'rev2', []) | 152 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], |
| 153 'compile', []) |
| 136 root_pipeline._LogUnexpectedAbort(True) | 154 root_pipeline._LogUnexpectedAbort(True) |
| 137 | 155 |
| 138 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 156 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 139 self.assertEqual(wf_analysis_status.ERROR, try_job.status) | 157 self.assertEqual(wf_analysis_status.ERROR, try_job.status) |
| 140 | 158 |
| 141 def testPipelineAbortedWithOutTryJobResult(self): | 159 def testPipelineAbortedWithOutTryJobResult(self): |
| 142 master_name = 'm' | 160 master_name = 'm' |
| 143 builder_name = 'b' | 161 builder_name = 'b' |
| 144 build_number = 1 | 162 build_number = 1 |
| 145 | 163 |
| 146 root_pipeline = TryJobPipeline( | 164 root_pipeline = TryJobPipeline( |
| 147 master_name, builder_name, build_number, 'rev1', 'rev2', []) | 165 master_name, builder_name, build_number, 'rev1', 'rev2', ['rev2'], |
| 166 'compile', []) |
| 148 root_pipeline._LogUnexpectedAbort(True) | 167 root_pipeline._LogUnexpectedAbort(True) |
| 149 | 168 |
| 150 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 169 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 151 | 170 |
| 152 self.assertIsNone(try_job) | 171 self.assertIsNone(try_job) |
| OLD | NEW |