blob: 1e7197128b2bd5718dc8630d992bcc488b3fac1f [file] [log] [blame]
# Copyright 2015 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 os
from pipeline_utils.appengine_third_party_pipeline_src_pipeline import handlers
from testing_utils import testing
from common import chromium_deps
from model.wf_analysis import WfAnalysis
from model import wf_analysis_status
from waterfall import buildbot
from waterfall.analyze_build_failure_pipeline import AnalyzeBuildFailurePipeline
from waterfall import lock_util
class AnalyzeBuildFailurePipelineTest(testing.AppengineTestCase):
app_module = handlers._APP
def _MockChangeLog(
self, urlfetch, user_name, revision, commit_position, file_path):
url = ('https://chromium.googlesource.com/chromium/src/+/%s?format=json'
% revision)
COMMIT_LOG_TEMPLATE = """)]}'
{
"commit": "REVISION",
"tree": "tree_rev",
"parents": [
"revX"
],
"author": {
"name": "USER_NAME@chromium.org",
"email": "USER_NAME@chromium.org",
"time": "Wed Jun 11 19:35:32 2014"
},
"committer": {
"name": "USER_NAME@chromium.org",
"email": "USER_NAME@chromium.org",
"time": "Wed Jun 11 19:35:32 2014"
},
"message":
"git-svn-id: svn://svn.chromium.org/chromium/src@COMMIT_POSITION bla",
"tree_diff": [
{
"type": "modify",
"old_id": "idX",
"old_mode": 33188,
"old_path": "FILE_PATH",
"new_id": "idY",
"new_mode": 33188,
"new_path": "FILE_PATH"
}
]
}
"""
commit_log = COMMIT_LOG_TEMPLATE.replace(
'REVISION', revision).replace('USER_NAME', user_name).replace(
'COMMIT_POSITION', str(commit_position)).replace('FILE_PATH', file_path)
urlfetch.register_handler(url, commit_log)
def _Setup(self, master_name, builder_name, build_number):
analysis = WfAnalysis.Create(master_name, builder_name, build_number)
analysis.status = wf_analysis_status.ANALYZING
analysis.put()
def MockWaitUntilDownloadAllowed(*_):
return True
self.mock(
lock_util, 'WaitUntilDownloadAllowed', MockWaitUntilDownloadAllowed)
with self.mock_urlfetch() as urlfetch:
# Mock build data.
for i in range(2):
build_url = buildbot.CreateBuildUrl(
master_name, builder_name, build_number - i, json_api=True)
file_name = os.path.join(os.path.dirname(__file__), 'data',
'm_b_%s.json' % (build_number - i))
with open(file_name, 'r') as f:
urlfetch.register_handler(build_url, f.read())
# Mock step log.
step_log_url = buildbot.CreateStdioLogUrl(
master_name, builder_name, build_number, 'a')
urlfetch.register_handler(
step_log_url, 'error in file a/b/x.cc:89 ...')
# Mock change logs.
self._MockChangeLog(urlfetch, 'user1', 'some_git_hash', 8888, 'a/b/x.cc')
self._MockChangeLog(
urlfetch, 'user1', '64c72819e898e952103b63eabc12772f9640af07',
8887, 'd/e/y.cc')
def MockGetChromeDependency(*_):
return {}
self.mock(chromium_deps, 'GetChromeDependency', MockGetChromeDependency)
def testBuildFailurePipeline(self):
master_name = 'm'
builder_name = 'b'
build_number = 124
self._Setup(master_name, builder_name, build_number)
root_pipeline = AnalyzeBuildFailurePipeline(master_name,
builder_name,
build_number)
root_pipeline.start(queue_name='default')
self.execute_queued_tasks()
expected_analysis_result = {
'failures': [
{
'step_name': 'a',
'first_failure': 124,
'last_pass': 123,
'suspected_cls': [
{
'build_number': 124,
'repo_name': 'chromium',
'revision': 'some_git_hash',
'commit_position': 8888,
'url': ('https://chromium.googlesource.com/chromium'
'/src/+/some_git_hash'),
'score': 2,
'hints': {
'modified x.cc (and it was in log)': 2,
},
}
],
}
]
}
analysis = WfAnalysis.Get(master_name, builder_name, build_number)
self.assertIsNotNone(analysis)
self.assertEqual(wf_analysis_status.ANALYZED, analysis.status)
self.assertEqual(expected_analysis_result, analysis.result)
self.assertIsNotNone(analysis.result_status)
def testBuildFailurePipelineStartWithNoneResultStatus(self):
master_name = 'm'
builder_name = 'b'
build_number = 124
self._Setup(master_name, builder_name, build_number)
root_pipeline = AnalyzeBuildFailurePipeline(master_name,
builder_name,
build_number)
root_pipeline._ResetAnalysis(master_name, builder_name, build_number)
analysis = WfAnalysis.Get(master_name, builder_name, build_number)
self.assertIsNotNone(analysis)
self.assertEqual(wf_analysis_status.ANALYZING, analysis.status)
self.assertIsNone(analysis.result_status)
def testAnalyzeBuildFailurePipelineAbortedWithAnalysis(self):
master_name = 'm'
builder_name = 'b'
build_number = 124
self._Setup(master_name, builder_name, build_number)
root_pipeline = AnalyzeBuildFailurePipeline(master_name,
builder_name,
build_number)
root_pipeline._LogUnexpectedAborting(True)
analysis = WfAnalysis.Get(master_name, builder_name, build_number)
self.assertIsNotNone(analysis)
self.assertEqual(wf_analysis_status.ERROR, analysis.status)
self.assertIsNone(analysis.result_status)
def testAnalyzeBuildFailurePipelineAbortedWithoutAnalysis(self):
master_name = 'm'
builder_name = 'b'
build_number = 124
root_pipeline = AnalyzeBuildFailurePipeline(master_name,
builder_name,
build_number)
root_pipeline._LogUnexpectedAborting(True)
analysis = WfAnalysis.Get(master_name, builder_name, build_number)
self.assertIsNone(analysis)
def testAnalyzeBuildFailurePipelineNotAborted(self):
master_name = 'm'
builder_name = 'b'
build_number = 124
self._Setup(master_name, builder_name, build_number)
root_pipeline = AnalyzeBuildFailurePipeline(master_name,
builder_name,
build_number)
root_pipeline._LogUnexpectedAborting(False)
analysis = WfAnalysis.Get(master_name, builder_name, build_number)
self.assertIsNotNone(analysis)
self.assertNotEqual(wf_analysis_status.ERROR, analysis.status)