| Index: appengine/findit/waterfall/test/detect_first_failure_pipeline_test.py
|
| diff --git a/appengine/findit/waterfall/test/detect_first_failure_pipeline_test.py b/appengine/findit/waterfall/test/detect_first_failure_pipeline_test.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cd1e3ad0e150ea2616f699912e1deb8bda26dbb1
|
| --- /dev/null
|
| +++ b/appengine/findit/waterfall/test/detect_first_failure_pipeline_test.py
|
| @@ -0,0 +1,179 @@
|
| +# Copyright 2014 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 datetime
|
| +import os
|
| +
|
| +from pipeline_utils.appengine_third_party_pipeline_src_pipeline import handlers
|
| +from testing_utils import testing
|
| +
|
| +from model.build import Build
|
| +from model.build_analysis import BuildAnalysis
|
| +from model.build_analysis_status import BuildAnalysisStatus
|
| +from waterfall import buildbot
|
| +from waterfall import detect_first_failure_pipeline
|
| +from waterfall.detect_first_failure_pipeline import DetectFirstFailurePipeline
|
| +from waterfall import lock_util
|
| +
|
| +
|
| +class DetectFirstFailureTest(testing.AppengineTestCase):
|
| + app_module = handlers._APP
|
| +
|
| + def setUp(self):
|
| + super(DetectFirstFailureTest, self).setUp()
|
| +
|
| + with self.mock_urlfetch() as urlfetch:
|
| + self.mocked_urlfetch = urlfetch
|
| +
|
| + def _WaitUntilDownloadAllowed(*_):
|
| + return True
|
| +
|
| + self.mock(lock_util, 'WaitUntilDownloadAllowed', _WaitUntilDownloadAllowed)
|
| +
|
| + def _TimeBeforeNowBySeconds(self, seconds):
|
| + return datetime.datetime.utcnow() - datetime.timedelta(0, seconds, 0)
|
| +
|
| + def testBuildDataNeedUpdating(self):
|
| + build = Build.CreateBuild('m', 'b', 1)
|
| + pipeline = DetectFirstFailurePipeline('m', 'b', 1)
|
| +
|
| + # Build data is not available.
|
| + self.assertTrue(pipeline._BuildDataNeedUpdating(build))
|
| +
|
| + # Build was not completed and data is not recent.
|
| + build.data = 'dummy'
|
| + build.completed = False
|
| + build.last_crawled_time = self._TimeBeforeNowBySeconds(360)
|
| + self.assertTrue(pipeline._BuildDataNeedUpdating(build))
|
| +
|
| + def testBuildDataNotNeedUpdating(self):
|
| + build = Build.CreateBuild('m', 'b', 1)
|
| + pipeline = DetectFirstFailurePipeline('m', 'b', 1)
|
| +
|
| + # Build is not completed yet but data is recent.
|
| + build.data = 'dummy'
|
| + build.completed = False
|
| + build.last_crawled_time = self._TimeBeforeNowBySeconds(60)
|
| + self.assertFalse(pipeline._BuildDataNeedUpdating(build))
|
| +
|
| + # Build was completed and data is final.
|
| + build.data = 'dummy'
|
| + build.completed = True
|
| + build.last_crawled_time = self._TimeBeforeNowBySeconds(360)
|
| + self.assertFalse(pipeline._BuildDataNeedUpdating(build))
|
| +
|
| +
|
| + def _CreateAndSaveBuildAnanlysis(
|
| + self, master_name, builder_name, build_number, status):
|
| + analysis = BuildAnalysis.CreateBuildAnalysis(
|
| + master_name, builder_name, build_number)
|
| + analysis.status = status
|
| + analysis.put()
|
| +
|
| + def _GetBuildData(self, master_name, builder_name, build_number):
|
| + file_name = os.path.join(
|
| + os.path.dirname(__file__), 'data',
|
| + '%s_%s_%d.json' % (master_name, builder_name, build_number))
|
| + with open(file_name, 'r') as f:
|
| + return f.read()
|
| +
|
| + def _MockUrlfetchWithBuildData(
|
| + self, master_name, builder_name, build_number, build_data=None):
|
| + """If build data is None, use json file in waterfall/test/data."""
|
| + if build_data is None:
|
| + build_data = self._GetBuildData(master_name, builder_name, build_number)
|
| +
|
| + build_url = buildbot.CreateBuildUrl(
|
| + master_name, builder_name, build_number, json_api=True)
|
| +
|
| + self.mocked_urlfetch.register_handler(build_url, build_data)
|
| +
|
| + def testLookBackUntilGreenBuild(self):
|
| + master_name = 'm'
|
| + builder_name = 'b'
|
| + build_number = 123
|
| +
|
| + self._CreateAndSaveBuildAnanlysis(
|
| + master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING)
|
| +
|
| + # Setup build data for builds:
|
| + # 123: mock urlfetch to ensure it is fetched.
|
| + self._MockUrlfetchWithBuildData(master_name, builder_name, 123)
|
| + # 122: mock a build in datastore to ensure it is not fetched again.
|
| + build = Build.CreateBuild(master_name, builder_name, 122)
|
| + build.data = self._GetBuildData(master_name, builder_name, 122)
|
| + build.completed = True
|
| + build.put()
|
| + self._MockUrlfetchWithBuildData(
|
| + master_name, builder_name, 122, build_data='Blow up if used!')
|
| + # 121: mock a build in datastore to ensure it is updated.
|
| + build = Build.CreateBuild(master_name, builder_name, 121)
|
| + build.data = 'Blow up if used!'
|
| + build.last_crawled_time = self._TimeBeforeNowBySeconds(7200)
|
| + build.completed = False
|
| + build.put()
|
| + self._MockUrlfetchWithBuildData(master_name, builder_name, 121)
|
| +
|
| + pipeline = DetectFirstFailurePipeline()
|
| + failure_info = pipeline.run(master_name, builder_name, build_number)
|
| +
|
| + expected_failed_steps = {
|
| + 'net_unittests': {
|
| + 'last_pass': 122,
|
| + 'current_failure': 123,
|
| + 'first_failure': 123
|
| + },
|
| + 'unit_tests': {
|
| + 'last_pass': 121,
|
| + 'current_failure': 123,
|
| + 'first_failure': 122
|
| + }
|
| + }
|
| +
|
| + self.assertEqual(expected_failed_steps, failure_info['failed_steps'])
|
| +
|
| + def testStopLookingBackIfAllFailedStepsPassedInLastBuild(self):
|
| + master_name = 'm'
|
| + builder_name = 'b'
|
| + build_number = 124
|
| +
|
| + self._CreateAndSaveBuildAnanlysis(
|
| + master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING)
|
| +
|
| + # Setup build data for builds:
|
| + self._MockUrlfetchWithBuildData(master_name, builder_name, 124)
|
| + self._MockUrlfetchWithBuildData(master_name, builder_name, 123)
|
| + self._MockUrlfetchWithBuildData(
|
| + master_name, builder_name, 122, build_data='Blow up if used!')
|
| +
|
| + pipeline = DetectFirstFailurePipeline()
|
| + failure_info = pipeline.run(master_name, builder_name, build_number)
|
| +
|
| + expected_failed_steps = {
|
| + 'a': {
|
| + 'last_pass': 123,
|
| + 'current_failure': 124,
|
| + 'first_failure': 124
|
| + }
|
| + }
|
| +
|
| + self.assertEqual(expected_failed_steps, failure_info['failed_steps'])
|
| +
|
| + def testAnalyzeSuccessfulBuild(self):
|
| + master_name = 'm'
|
| + builder_name = 'b'
|
| + build_number = 121
|
| +
|
| + self._CreateAndSaveBuildAnanlysis(
|
| + master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING)
|
| +
|
| + # Setup build data for builds:
|
| + self._MockUrlfetchWithBuildData(master_name, builder_name, 121)
|
| + self._MockUrlfetchWithBuildData(
|
| + master_name, builder_name, 120, build_data='Blow up if used!')
|
| +
|
| + pipeline = DetectFirstFailurePipeline()
|
| + failure_info = pipeline.run(master_name, builder_name, build_number)
|
| +
|
| + self.assertFalse(failure_info['failed'])
|
|
|