OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 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 datetime |
| 6 import os |
| 7 |
| 8 from pipeline_utils.appengine_third_party_pipeline_src_pipeline import handlers |
| 9 from testing_utils import testing |
| 10 |
| 11 from model.build import Build |
| 12 from model.build_analysis import BuildAnalysis |
| 13 from model.build_analysis_status import BuildAnalysisStatus |
| 14 from waterfall import buildbot |
| 15 from waterfall import detect_first_failure_pipeline |
| 16 from waterfall.detect_first_failure_pipeline import DetectFirstFailurePipeline |
| 17 from waterfall import lock_util |
| 18 |
| 19 |
| 20 class DetectFirstFailureTest(testing.AppengineTestCase): |
| 21 app_module = handlers._APP |
| 22 |
| 23 def setUp(self): |
| 24 super(DetectFirstFailureTest, self).setUp() |
| 25 |
| 26 with self.mock_urlfetch() as urlfetch: |
| 27 self.mocked_urlfetch = urlfetch |
| 28 |
| 29 def _WaitUntilDownloadAllowed(*_): |
| 30 return True |
| 31 |
| 32 self.mock(lock_util, 'WaitUntilDownloadAllowed', _WaitUntilDownloadAllowed) |
| 33 |
| 34 def _TimeBeforeNowBySeconds(self, seconds): |
| 35 return datetime.datetime.utcnow() - datetime.timedelta(0, seconds, 0) |
| 36 |
| 37 def testBuildDataNeedUpdating(self): |
| 38 build = Build.CreateBuild('m', 'b', 1) |
| 39 pipeline = DetectFirstFailurePipeline('m', 'b', 1) |
| 40 |
| 41 # Build data is not available. |
| 42 self.assertTrue(pipeline._BuildDataNeedUpdating(build)) |
| 43 |
| 44 # Build was not completed and data is not recent. |
| 45 build.data = 'dummy' |
| 46 build.completed = False |
| 47 build.last_crawled_time = self._TimeBeforeNowBySeconds(360) |
| 48 self.assertTrue(pipeline._BuildDataNeedUpdating(build)) |
| 49 |
| 50 def testBuildDataNotNeedUpdating(self): |
| 51 build = Build.CreateBuild('m', 'b', 1) |
| 52 pipeline = DetectFirstFailurePipeline('m', 'b', 1) |
| 53 |
| 54 # Build is not completed yet but data is recent. |
| 55 build.data = 'dummy' |
| 56 build.completed = False |
| 57 build.last_crawled_time = self._TimeBeforeNowBySeconds(60) |
| 58 self.assertFalse(pipeline._BuildDataNeedUpdating(build)) |
| 59 |
| 60 # Build was completed and data is final. |
| 61 build.data = 'dummy' |
| 62 build.completed = True |
| 63 build.last_crawled_time = self._TimeBeforeNowBySeconds(360) |
| 64 self.assertFalse(pipeline._BuildDataNeedUpdating(build)) |
| 65 |
| 66 |
| 67 def _CreateAndSaveBuildAnanlysis( |
| 68 self, master_name, builder_name, build_number, status): |
| 69 analysis = BuildAnalysis.CreateBuildAnalysis( |
| 70 master_name, builder_name, build_number) |
| 71 analysis.status = status |
| 72 analysis.put() |
| 73 |
| 74 def _GetBuildData(self, master_name, builder_name, build_number): |
| 75 file_name = os.path.join( |
| 76 os.path.dirname(__file__), 'data', |
| 77 '%s_%s_%d.json' % (master_name, builder_name, build_number)) |
| 78 with open(file_name, 'r') as f: |
| 79 return f.read() |
| 80 |
| 81 def _MockUrlfetchWithBuildData( |
| 82 self, master_name, builder_name, build_number, build_data=None): |
| 83 """If build data is None, use json file in waterfall/test/data.""" |
| 84 if build_data is None: |
| 85 build_data = self._GetBuildData(master_name, builder_name, build_number) |
| 86 |
| 87 build_url = buildbot.CreateBuildUrl( |
| 88 master_name, builder_name, build_number, json_api=True) |
| 89 |
| 90 self.mocked_urlfetch.register_handler(build_url, build_data) |
| 91 |
| 92 def testLookBackUntilGreenBuild(self): |
| 93 master_name = 'm' |
| 94 builder_name = 'b' |
| 95 build_number = 123 |
| 96 |
| 97 self._CreateAndSaveBuildAnanlysis( |
| 98 master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING) |
| 99 |
| 100 # Setup build data for builds: |
| 101 # 123: mock urlfetch to ensure it is fetched. |
| 102 self._MockUrlfetchWithBuildData(master_name, builder_name, 123) |
| 103 # 122: mock a build in datastore to ensure it is not fetched again. |
| 104 build = Build.CreateBuild(master_name, builder_name, 122) |
| 105 build.data = self._GetBuildData(master_name, builder_name, 122) |
| 106 build.completed = True |
| 107 build.put() |
| 108 self._MockUrlfetchWithBuildData( |
| 109 master_name, builder_name, 122, build_data='Blow up if used!') |
| 110 # 121: mock a build in datastore to ensure it is updated. |
| 111 build = Build.CreateBuild(master_name, builder_name, 121) |
| 112 build.data = 'Blow up if used!' |
| 113 build.last_crawled_time = self._TimeBeforeNowBySeconds(7200) |
| 114 build.completed = False |
| 115 build.put() |
| 116 self._MockUrlfetchWithBuildData(master_name, builder_name, 121) |
| 117 |
| 118 pipeline = DetectFirstFailurePipeline() |
| 119 failure_info = pipeline.run(master_name, builder_name, build_number) |
| 120 |
| 121 expected_failed_steps = { |
| 122 'net_unittests': { |
| 123 'last_pass': 122, |
| 124 'current_failure': 123, |
| 125 'first_failure': 123 |
| 126 }, |
| 127 'unit_tests': { |
| 128 'last_pass': 121, |
| 129 'current_failure': 123, |
| 130 'first_failure': 122 |
| 131 } |
| 132 } |
| 133 |
| 134 self.assertEqual(expected_failed_steps, failure_info['failed_steps']) |
| 135 |
| 136 def testStopLookingBackIfAllFailedStepsPassedInLastBuild(self): |
| 137 master_name = 'm' |
| 138 builder_name = 'b' |
| 139 build_number = 124 |
| 140 |
| 141 self._CreateAndSaveBuildAnanlysis( |
| 142 master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING) |
| 143 |
| 144 # Setup build data for builds: |
| 145 self._MockUrlfetchWithBuildData(master_name, builder_name, 124) |
| 146 self._MockUrlfetchWithBuildData(master_name, builder_name, 123) |
| 147 self._MockUrlfetchWithBuildData( |
| 148 master_name, builder_name, 122, build_data='Blow up if used!') |
| 149 |
| 150 pipeline = DetectFirstFailurePipeline() |
| 151 failure_info = pipeline.run(master_name, builder_name, build_number) |
| 152 |
| 153 expected_failed_steps = { |
| 154 'a': { |
| 155 'last_pass': 123, |
| 156 'current_failure': 124, |
| 157 'first_failure': 124 |
| 158 } |
| 159 } |
| 160 |
| 161 self.assertEqual(expected_failed_steps, failure_info['failed_steps']) |
| 162 |
| 163 def testAnalyzeSuccessfulBuild(self): |
| 164 master_name = 'm' |
| 165 builder_name = 'b' |
| 166 build_number = 121 |
| 167 |
| 168 self._CreateAndSaveBuildAnanlysis( |
| 169 master_name, builder_name, build_number, BuildAnalysisStatus.ANALYZING) |
| 170 |
| 171 # Setup build data for builds: |
| 172 self._MockUrlfetchWithBuildData(master_name, builder_name, 121) |
| 173 self._MockUrlfetchWithBuildData( |
| 174 master_name, builder_name, 120, build_data='Blow up if used!') |
| 175 |
| 176 pipeline = DetectFirstFailurePipeline() |
| 177 failure_info = pipeline.run(master_name, builder_name, build_number) |
| 178 |
| 179 self.assertFalse(failure_info['failed']) |
OLD | NEW |