| 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 from datetime import datetime | 5 from datetime import datetime |
| 6 import json | 6 import json |
| 7 import time | 7 import time |
| 8 | 8 |
| 9 from common.waterfall import try_job_error |
| 9 from common.waterfall import buildbucket_client | 10 from common.waterfall import buildbucket_client |
| 10 from model import analysis_status | 11 from model import analysis_status |
| 11 from model.wf_try_job import WfTryJob | 12 from model.wf_try_job import WfTryJob |
| 12 from model.wf_try_job_data import WfTryJobData | 13 from model.wf_try_job_data import WfTryJobData |
| 14 from waterfall import waterfall_config |
| 13 from waterfall.monitor_try_job_pipeline import MonitorTryJobPipeline | 15 from waterfall.monitor_try_job_pipeline import MonitorTryJobPipeline |
| 14 from waterfall.test import wf_testcase | 16 from waterfall.test import wf_testcase |
| 15 from waterfall.try_job_type import TryJobType | 17 from waterfall.try_job_type import TryJobType |
| 16 | 18 |
| 17 | 19 |
| 18 # A counter to enable different responses to requests in a loop. | 20 # A counter to enable different responses to requests in a loop. |
| 19 REQUEST_COUNTER = { | 21 REQUEST_COUNTER = { |
| 20 '1': 0, | 22 '1': 0, |
| 21 '2': 0, | 23 '2': 0, |
| 22 '3': 0 | 24 '3': 0 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 'metadata': { | 163 'metadata': { |
| 162 'regression_range_size': 2 | 164 'regression_range_size': 2 |
| 163 } | 165 } |
| 164 } | 166 } |
| 165 } | 167 } |
| 166 }) | 168 }) |
| 167 } | 169 } |
| 168 build = buildbucket_client.BuildbucketBuild(build_data) | 170 build = buildbucket_client.BuildbucketBuild(build_data) |
| 169 try_job_data = WfTryJobData.Create(try_job_id) | 171 try_job_data = WfTryJobData.Create(try_job_id) |
| 170 | 172 |
| 173 expected_error_dict = { |
| 174 'message': 'Try job monitoring was abandoned.', |
| 175 'reason': ('Timeout after %s hours' % |
| 176 waterfall_config.GetTryJobSettings().get( |
| 177 'job_timeout_hours')) |
| 178 } |
| 179 |
| 171 MonitorTryJobPipeline._UpdateTryJobMetadata( | 180 MonitorTryJobPipeline._UpdateTryJobMetadata( |
| 172 try_job_data, None, build, None, False) | 181 try_job_data, None, build, None, False) |
| 173 try_job_data = WfTryJobData.Get(try_job_id) | 182 try_job_data = WfTryJobData.Get(try_job_id) |
| 174 self.assertIsNone(try_job_data.error) | 183 self.assertIsNone(try_job_data.error) |
| 175 self.assertEqual(try_job_data.regression_range_size, 2) | 184 self.assertEqual(try_job_data.regression_range_size, 2) |
| 176 self.assertEqual(try_job_data.number_of_commits_analyzed, 2) | 185 self.assertEqual(try_job_data.number_of_commits_analyzed, 2) |
| 177 self.assertEqual(try_job_data.end_time, datetime(2016, 2, 1, 22, 59, 34)) | 186 self.assertEqual(try_job_data.end_time, datetime(2016, 2, 1, 22, 59, 34)) |
| 178 self.assertEqual(try_job_data.request_time, | 187 self.assertEqual(try_job_data.request_time, |
| 179 datetime(2016, 2, 1, 22, 59, 30)) | 188 datetime(2016, 2, 1, 22, 59, 30)) |
| 180 self.assertEqual(try_job_data.try_job_url, url) | 189 self.assertEqual(try_job_data.try_job_url, url) |
| 181 | 190 |
| 182 MonitorTryJobPipeline._UpdateTryJobMetadata( | 191 MonitorTryJobPipeline._UpdateTryJobMetadata( |
| 183 try_job_data, None, build, None, True) | 192 try_job_data, None, build, None, True) |
| 184 self.assertEqual(try_job_data.error, | 193 self.assertEqual(try_job_data.error, expected_error_dict) |
| 185 {'message': 'Try job monitoring was abandoned.', | 194 self.assertEqual(try_job_data.error_code, try_job_error.TIMEOUT) |
| 186 'reason': MonitorTryJobPipeline.TIMEOUT}) | |
| 187 | 195 |
| 188 def testGetTryJobsForCompileSuccess(self): | 196 def testGetTryJobsForCompileSuccess(self): |
| 189 master_name = 'm' | 197 master_name = 'm' |
| 190 builder_name = 'b' | 198 builder_name = 'b' |
| 191 build_number = 1 | 199 build_number = 1 |
| 192 try_job_id = '1' | 200 try_job_id = '1' |
| 193 regression_range_size = 2 | 201 regression_range_size = 2 |
| 194 | 202 |
| 195 try_job = WfTryJob.Create(master_name, builder_name, build_number) | 203 try_job = WfTryJob.Create(master_name, builder_name, build_number) |
| 196 try_job_data = WfTryJobData.Create(try_job_id) | 204 try_job_data = WfTryJobData.Create(try_job_id) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 try_job_id = '3' | 299 try_job_id = '3' |
| 292 | 300 |
| 293 try_job = WfTryJob.Create(master_name, builder_name, build_number).put() | 301 try_job = WfTryJob.Create(master_name, builder_name, build_number).put() |
| 294 | 302 |
| 295 pipeline = MonitorTryJobPipeline() | 303 pipeline = MonitorTryJobPipeline() |
| 296 pipeline._UpdateTryJobResult( | 304 pipeline._UpdateTryJobResult( |
| 297 buildbucket_client.BuildbucketBuild.STARTED, master_name, builder_name, | 305 buildbucket_client.BuildbucketBuild.STARTED, master_name, builder_name, |
| 298 build_number, TryJobType.TEST, try_job_id, 'url') | 306 build_number, TryJobType.TEST, try_job_id, 'url') |
| 299 try_job = WfTryJob.Get(master_name, builder_name, build_number) | 307 try_job = WfTryJob.Get(master_name, builder_name, build_number) |
| 300 self.assertEqual(analysis_status.RUNNING, try_job.status) | 308 self.assertEqual(analysis_status.RUNNING, try_job.status) |
| 309 |
| 310 def testGetErrorForNoError(self): |
| 311 build_response = { |
| 312 'id': 1, |
| 313 'url': 'url', |
| 314 'status': 'COMPLETED', |
| 315 'completed_ts': '1454367574000000', |
| 316 'created_ts': '1454367570000000', |
| 317 'result_details_json': json.dumps({ |
| 318 'properties': { |
| 319 'report': { |
| 320 'result': { |
| 321 'rev1': 'passed', |
| 322 'rev2': 'failed' |
| 323 }, |
| 324 'metadata': { |
| 325 'regression_range_size': 2 |
| 326 } |
| 327 } |
| 328 } |
| 329 }) |
| 330 } |
| 331 self.assertEqual( |
| 332 MonitorTryJobPipeline._GetError(build_response, None, False), |
| 333 (None, None)) |
| 334 self.assertEqual(MonitorTryJobPipeline._GetError({}, None, False), |
| 335 (None, None)) |
| 336 |
| 337 def testGetErrorForTimeout(self): |
| 338 expected_error_dict = { |
| 339 'message': 'Try job monitoring was abandoned.', |
| 340 'reason': ('Timeout after %s hours' % |
| 341 waterfall_config.GetTryJobSettings().get( |
| 342 'job_timeout_hours')) |
| 343 } |
| 344 |
| 345 self.assertEqual( |
| 346 MonitorTryJobPipeline._GetError({}, None, True), |
| 347 (expected_error_dict, try_job_error.TIMEOUT)) |
| 348 |
| 349 def testGetErrorForBuildbucketReportedError(self): |
| 350 build_response = { |
| 351 'result_details_json': json.dumps({ |
| 352 'error': { |
| 353 'message': 'Builder b not found' |
| 354 } |
| 355 }) |
| 356 } |
| 357 |
| 358 expected_error_dict = { |
| 359 'message': 'Buildbucket reported an error.', |
| 360 'reason': 'Builder b not found' |
| 361 } |
| 362 |
| 363 self.assertEqual( |
| 364 MonitorTryJobPipeline._GetError(build_response, None, False), |
| 365 (expected_error_dict, try_job_error.CI_REPORTED_ERROR)) |
| 366 |
| 367 def testGetErrorUnknown(self): |
| 368 build_response = { |
| 369 'result_details_json': json.dumps({ |
| 370 'error': { |
| 371 'abc': 'abc' |
| 372 } |
| 373 }) |
| 374 } |
| 375 |
| 376 expected_error_dict = { |
| 377 'message': 'Buildbucket reported an error.', |
| 378 'reason': MonitorTryJobPipeline.UNKNOWN |
| 379 } |
| 380 |
| 381 self.assertEqual( |
| 382 MonitorTryJobPipeline._GetError(build_response, None, False), |
| 383 (expected_error_dict, try_job_error.CI_REPORTED_ERROR)) |
| 384 |
| 385 def testGetErrorInfraFailure(self): |
| 386 build_response = { |
| 387 'result_details_json': json.dumps({ |
| 388 'properties': { |
| 389 'report': { |
| 390 'metadata': { |
| 391 'infra_failure': True |
| 392 } |
| 393 } |
| 394 } |
| 395 }) |
| 396 } |
| 397 |
| 398 expected_error_dict = { |
| 399 'message': 'Try job encountered an infra issue during execution.', |
| 400 'reason': MonitorTryJobPipeline.UNKNOWN |
| 401 } |
| 402 |
| 403 self.assertEqual( |
| 404 MonitorTryJobPipeline._GetError(build_response, None, False), |
| 405 (expected_error_dict, try_job_error.INFRA_FAILURE)) |
| 406 |
| 407 def testGetErrorReportMissing(self): |
| 408 build_response = { |
| 409 'result_details_json': json.dumps({ |
| 410 'properties': {} |
| 411 }) |
| 412 } |
| 413 |
| 414 expected_error_dict = { |
| 415 'message': 'No result report was found.', |
| 416 'reason': MonitorTryJobPipeline.UNKNOWN |
| 417 } |
| 418 |
| 419 self.assertEqual( |
| 420 MonitorTryJobPipeline._GetError(build_response, None, False), |
| 421 (expected_error_dict, try_job_error.UNKNOWN)) |
| OLD | NEW |