| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 common import constants | 5 from common import constants |
| 6 from common.pipeline_wrapper import pipeline_handlers | 6 from common.pipeline_wrapper import pipeline_handlers |
| 7 from model import analysis_status | 7 from model import analysis_status |
| 8 from model.flake.master_flake_analysis import MasterFlakeAnalysis | 8 from model.flake.master_flake_analysis import MasterFlakeAnalysis |
| 9 from model.flake.flake_swarming_task import FlakeSwarmingTask |
| 9 from waterfall.flake import recursive_flake_pipeline | 10 from waterfall.flake import recursive_flake_pipeline |
| 10 from waterfall.flake.recursive_flake_pipeline import NextBuildNumberPipeline | 11 from waterfall.flake.recursive_flake_pipeline import NextBuildNumberPipeline |
| 11 from waterfall.flake.recursive_flake_pipeline import RecursiveFlakePipeline | 12 from waterfall.flake.recursive_flake_pipeline import RecursiveFlakePipeline |
| 12 from waterfall.test import wf_testcase | 13 from waterfall.test import wf_testcase |
| 13 | 14 |
| 14 | 15 |
| 15 class RecursiveFlakePipelineTest(wf_testcase.WaterfallTestCase): | 16 class RecursiveFlakePipelineTest(wf_testcase.WaterfallTestCase): |
| 16 app_module = pipeline_handlers._APP | 17 app_module = pipeline_handlers._APP |
| 17 | 18 |
| 18 def _CreateAndSaveMasterFlakeAnalysis( | 19 def _CreateAndSaveMasterFlakeAnalysis( |
| 19 self, master_name, builder_name, build_number, | 20 self, master_name, builder_name, build_number, |
| 20 step_name, test_name, status): | 21 step_name, test_name, status): |
| 21 analysis = MasterFlakeAnalysis.Create( | 22 analysis = MasterFlakeAnalysis.Create( |
| 22 master_name, builder_name, build_number, step_name, test_name) | 23 master_name, builder_name, build_number, step_name, test_name) |
| 23 analysis.status = status | 24 analysis.status = status |
| 24 analysis.put() | 25 analysis.put() |
| 25 | 26 |
| 27 def _CreateAndSaveFlakeSwarmingTask( |
| 28 self, master_name, builder_name, build_number, |
| 29 step_name, test_name, status): |
| 30 flake_swarming_task = FlakeSwarmingTask.Create( |
| 31 master_name, builder_name, build_number, step_name, test_name) |
| 32 flake_swarming_task.status = status |
| 33 flake_swarming_task.put() |
| 34 |
| 26 def testRecursiveFlakePipeline(self): | 35 def testRecursiveFlakePipeline(self): |
| 27 master_name = 'm' | 36 master_name = 'm' |
| 28 builder_name = 'b' | 37 builder_name = 'b' |
| 29 master_build_number = 124 | 38 master_build_number = 100 |
| 30 build_number = 124 | 39 build_number = 100 |
| 31 run_build_number = 124 | 40 run_build_number = 100 |
| 32 step_name = 's' | 41 step_name = 's' |
| 33 test_name = 't' | 42 test_name = 't' |
| 34 test_result_future = 'test_result_future' | 43 test_result_future = 'test_result_future' |
| 35 queue_name = constants.DEFAULT_QUEUE | 44 queue_name = constants.DEFAULT_QUEUE |
| 36 task_id = 'task_id' | 45 task_id = 'task_id' |
| 37 | 46 |
| 47 algo_dict = { |
| 48 'flakes_in_a_row': 0, |
| 49 'stable_in_a_row': 0, |
| 50 'stabled_out': False, |
| 51 'flaked_out': False, |
| 52 'last_build_number': 0 |
| 53 } |
| 54 |
| 38 self.MockPipeline( | 55 self.MockPipeline( |
| 39 recursive_flake_pipeline.TriggerFlakeSwarmingTaskPipeline, | 56 recursive_flake_pipeline.TriggerFlakeSwarmingTaskPipeline, |
| 40 'task_id', | 57 'task_id', |
| 41 expected_args=[master_name, builder_name, | 58 expected_args=[master_name, builder_name, |
| 42 run_build_number, step_name, [test_name]], | 59 run_build_number, step_name, [test_name]], |
| 43 expected_kwargs={}) | 60 expected_kwargs={}) |
| 61 |
| 44 self.MockPipeline( | 62 self.MockPipeline( |
| 45 recursive_flake_pipeline.ProcessFlakeSwarmingTaskResultPipeline, | 63 recursive_flake_pipeline.ProcessFlakeSwarmingTaskResultPipeline, |
| 46 'test_result_future', | 64 'test_result_future', |
| 47 expected_args=[master_name, builder_name, | 65 expected_args=[master_name, builder_name, |
| 48 run_build_number, step_name, task_id, | 66 run_build_number, step_name, task_id, |
| 49 master_build_number, test_name], | 67 master_build_number, test_name], |
| 50 expected_kwargs={}) | 68 expected_kwargs={}) |
| 69 |
| 51 self.MockPipeline( | 70 self.MockPipeline( |
| 52 recursive_flake_pipeline.NextBuildNumberPipeline, | 71 recursive_flake_pipeline.NextBuildNumberPipeline, |
| 53 '', | 72 '', |
| 54 expected_args=[master_name, builder_name, master_build_number, | 73 expected_args=[master_name, builder_name, master_build_number, |
| 55 step_name, test_name, test_result_future, | 74 build_number, step_name, test_name, |
| 56 queue_name], | 75 test_result_future, queue_name, algo_dict], |
| 57 expected_kwargs={}) | 76 expected_kwargs={}) |
| 58 | 77 |
| 59 rfp = RecursiveFlakePipeline(master_name, builder_name, build_number, | 78 rfp = RecursiveFlakePipeline(master_name, builder_name, build_number, |
| 60 step_name, test_name, master_build_number, | 79 step_name, test_name, master_build_number, |
| 61 queue_name=queue_name) | 80 algo_dict=algo_dict, queue_name=queue_name) |
| 81 |
| 62 rfp.start(queue_name=queue_name) | 82 rfp.start(queue_name=queue_name) |
| 63 self.execute_queued_tasks() | 83 self.execute_queued_tasks() |
| 64 | 84 |
| 65 def testNextBuildPipelineForNewRecursion(self): | 85 def testNextBuildPipelineForNewRecursionFirstFlake(self): |
| 66 master_name = 'm' | 86 master_name = 'm' |
| 67 builder_name = 'b' | 87 builder_name = 'b' |
| 68 master_build_number = 124 | 88 master_build_number = 100 |
| 69 build_number = 124 | 89 build_number = 100 |
| 70 step_name = 's' | 90 step_name = 's' |
| 71 test_name = 't' | 91 test_name = 't' |
| 72 test_result_future = 'trf' | 92 test_result_future = 'trf' |
| 73 queue_name = constants.DEFAULT_QUEUE | 93 queue_name = constants.DEFAULT_QUEUE |
| 74 | 94 algo_dict = { |
| 75 self._CreateAndSaveMasterFlakeAnalysis( | 95 'flakes_in_a_row': 0, |
| 76 master_name, builder_name, build_number, step_name, | 96 'stable_in_a_row': 0, |
| 77 test_name, status=analysis_status.PENDING | 97 'stabled_out': False, |
| 78 ) | 98 'flaked_out': False, |
| 79 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, | 99 'last_build_number': 0 |
| 80 build_number, step_name, test_name) | 100 } |
| 81 analysis.build_numbers.append(124) | 101 self._CreateAndSaveMasterFlakeAnalysis( |
| 102 master_name, builder_name, build_number, step_name, |
| 103 test_name, status=analysis_status.PENDING |
| 104 ) |
| 105 self._CreateAndSaveFlakeSwarmingTask( |
| 106 master_name, builder_name, build_number, step_name, |
| 107 test_name, status=analysis_status.COMPLETED |
| 108 ) |
| 109 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 110 build_number, step_name, test_name) |
| 111 analysis.success_rates.append(.08) |
| 112 analysis.build_numbers.append(100) |
| 113 analysis.put() |
| 114 |
| 115 NextBuildNumberPipeline.run( |
| 116 NextBuildNumberPipeline(), master_name, builder_name, |
| 117 master_build_number, build_number, step_name, test_name, |
| 118 test_result_future, queue_name, algo_dict) |
| 119 self.assertEquals(algo_dict['flakes_in_a_row'], 1) |
| 120 |
| 121 def testNextBuildPipelineForNewRecursionFirstStable(self): |
| 122 master_name = 'm' |
| 123 builder_name = 'b' |
| 124 master_build_number = 100 |
| 125 build_number = 100 |
| 126 step_name = 's' |
| 127 test_name = 't' |
| 128 test_result_future = 'trf' |
| 129 queue_name = constants.DEFAULT_QUEUE |
| 130 algo_dict = { |
| 131 'flakes_in_a_row': 0, |
| 132 'stable_in_a_row': 0, |
| 133 'stabled_out': False, |
| 134 'flaked_out': False, |
| 135 'last_build_number': 0 |
| 136 } |
| 137 self._CreateAndSaveMasterFlakeAnalysis( |
| 138 master_name, builder_name, build_number, step_name, |
| 139 test_name, status=analysis_status.PENDING |
| 140 ) |
| 141 self._CreateAndSaveFlakeSwarmingTask( |
| 142 master_name, builder_name, build_number, step_name, |
| 143 test_name, status=analysis_status.COMPLETED |
| 144 ) |
| 145 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 146 build_number, step_name, test_name) |
| 147 analysis.success_rates.append(0) |
| 148 analysis.build_numbers.append(100) |
| 149 analysis.put() |
| 150 |
| 151 NextBuildNumberPipeline.run( |
| 152 NextBuildNumberPipeline(), master_name, builder_name, |
| 153 master_build_number, build_number, step_name, |
| 154 test_name, test_result_future, queue_name, algo_dict) |
| 155 self.assertEquals(algo_dict['stable_in_a_row'], 1) |
| 156 |
| 157 def testNextBuildPipelineForNewRecursionFlakeInARow(self): |
| 158 master_name = 'm' |
| 159 builder_name = 'b' |
| 160 master_build_number = 100 |
| 161 build_number = 100 |
| 162 step_name = 's' |
| 163 test_name = 't' |
| 164 test_result_future = 'trf' |
| 165 queue_name = constants.DEFAULT_QUEUE |
| 166 algo_dict = { |
| 167 'flakes_in_a_row': 0, |
| 168 'stable_in_a_row': 4, |
| 169 'stabled_out': False, |
| 170 'flaked_out': False, |
| 171 'last_build_number': 0 |
| 172 } |
| 173 self._CreateAndSaveMasterFlakeAnalysis( |
| 174 master_name, builder_name, build_number, step_name, |
| 175 test_name, status=analysis_status.PENDING |
| 176 ) |
| 177 self._CreateAndSaveFlakeSwarmingTask( |
| 178 master_name, builder_name, build_number, step_name, |
| 179 test_name, status=analysis_status.COMPLETED |
| 180 ) |
| 181 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 182 build_number, step_name, test_name) |
| 183 analysis.success_rates.append(0) |
| 184 analysis.build_numbers.append(100) |
| 185 analysis.put() |
| 186 |
| 187 NextBuildNumberPipeline.run( |
| 188 NextBuildNumberPipeline(), master_name, builder_name, |
| 189 master_build_number, build_number, step_name, |
| 190 test_name, test_result_future, queue_name, algo_dict) |
| 191 self.assertEquals(algo_dict['stabled_out'], True) |
| 192 |
| 193 def testNextBuildPipelineForNewRecursionStableInARow(self): |
| 194 master_name = 'm' |
| 195 builder_name = 'b' |
| 196 master_build_number = 100 |
| 197 build_number = 100 |
| 198 step_name = 's' |
| 199 test_name = 't' |
| 200 test_result_future = 'trf' |
| 201 queue_name = constants.DEFAULT_QUEUE |
| 202 algo_dict = { |
| 203 'flakes_in_a_row': 4, |
| 204 'stable_in_a_row': 0, |
| 205 'stabled_out': False, |
| 206 'flaked_out': False, |
| 207 'last_build_number': 0 |
| 208 } |
| 209 self._CreateAndSaveMasterFlakeAnalysis( |
| 210 master_name, builder_name, build_number, step_name, |
| 211 test_name, status=analysis_status.PENDING |
| 212 ) |
| 213 self._CreateAndSaveFlakeSwarmingTask( |
| 214 master_name, builder_name, build_number, step_name, |
| 215 test_name, status=analysis_status.COMPLETED |
| 216 ) |
| 217 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 218 build_number, step_name, test_name) |
| 219 analysis.success_rates.append(.50) |
| 220 analysis.build_numbers.append(100) |
| 221 analysis.put() |
| 222 |
| 223 NextBuildNumberPipeline.run( |
| 224 NextBuildNumberPipeline(), master_name, builder_name, |
| 225 master_build_number, build_number, step_name, |
| 226 test_name, test_result_future, queue_name, algo_dict) |
| 227 self.assertEquals(algo_dict['flaked_out'], True) |
| 228 |
| 229 def testNextBuildPipelineForNewRecursionStabledFlakedOut(self): |
| 230 master_name = 'm' |
| 231 builder_name = 'b' |
| 232 master_build_number = 100 |
| 233 build_number = 100 |
| 234 step_name = 's' |
| 235 test_name = 't' |
| 236 test_result_future = 'trf' |
| 237 queue_name = constants.DEFAULT_QUEUE |
| 238 algo_dict = { |
| 239 'flakes_in_a_row': 4, |
| 240 'stable_in_a_row': 0, |
| 241 'stabled_out': True, |
| 242 'flaked_out': False, |
| 243 'last_build_number': 0 |
| 244 } |
| 245 self._CreateAndSaveMasterFlakeAnalysis( |
| 246 master_name, builder_name, build_number, step_name, |
| 247 test_name, status=analysis_status.PENDING |
| 248 ) |
| 249 self._CreateAndSaveFlakeSwarmingTask( |
| 250 master_name, builder_name, build_number, step_name, |
| 251 test_name, status=analysis_status.COMPLETED |
| 252 ) |
| 253 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 254 build_number, step_name, test_name) |
| 255 analysis.success_rates.append(.50) |
| 256 analysis.build_numbers.append(100) |
| 82 analysis.put() | 257 analysis.put() |
| 83 | 258 |
| 84 queue_name = {'x': False} | 259 queue_name = {'x': False} |
| 85 # Unused argument (class method calls in python) - pylint: disable=W0613 | 260 def my_mocked_run(arg1, queue_name): # pylint: disable=unused-argument |
| 86 def my_mocked_run(arg1, queue_name): | 261 queue_name['x'] = True # pragma: no cover |
| 87 queue_name['x'] = True | |
| 88 | 262 |
| 89 self.mock( | 263 self.mock( |
| 90 recursive_flake_pipeline.RecursiveFlakePipeline, 'start', my_mocked_run) | 264 recursive_flake_pipeline.RecursiveFlakePipeline, 'start', my_mocked_run) |
| 91 NextBuildNumberPipeline.run( | 265 NextBuildNumberPipeline.run( |
| 92 NextBuildNumberPipeline(), master_name, builder_name, | 266 NextBuildNumberPipeline(), master_name, builder_name, |
| 93 master_build_number, step_name, test_name, test_result_future, | 267 master_build_number, build_number, step_name, test_name, |
| 94 queue_name) | 268 test_result_future, queue_name, algo_dict) |
| 95 self.assertTrue(queue_name['x']) | 269 self.assertFalse(queue_name['x']) |
| 96 | 270 |
| 97 def testNextBuildPipelineForNewRecursionWhenDone(self): | 271 def testNextBuildPipelineForNewRecursionLessThanLastBuildNumber(self): |
| 98 master_name = 'm' | 272 master_name = 'm' |
| 99 builder_name = 'b' | 273 builder_name = 'b' |
| 100 master_build_number = 124 | 274 master_build_number = 100 |
| 101 build_number = 124 | 275 build_number = 100 |
| 102 step_name = 's' | 276 step_name = 's' |
| 103 test_name = 't' | 277 test_name = 't' |
| 104 test_result_future = 'trf' | 278 test_result_future = 'trf' |
| 105 queue_name = constants.DEFAULT_QUEUE | 279 queue_name = constants.DEFAULT_QUEUE |
| 106 | 280 algo_dict = { |
| 107 self._CreateAndSaveMasterFlakeAnalysis( | 281 'flakes_in_a_row': 0, |
| 108 master_name, builder_name, build_number, step_name, | 282 'stable_in_a_row': 0, |
| 109 test_name, status=analysis_status.PENDING | 283 'stabled_out': False, |
| 110 ) | 284 'flaked_out': False, |
| 111 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, | 285 'last_build_number': 200 |
| 112 build_number, step_name, test_name) | 286 } |
| 113 for _ in range(10): | 287 self._CreateAndSaveMasterFlakeAnalysis( |
| 114 analysis.build_numbers.append(124) | 288 master_name, builder_name, build_number, step_name, |
| 289 test_name, status=analysis_status.PENDING |
| 290 ) |
| 291 self._CreateAndSaveFlakeSwarmingTask( |
| 292 master_name, builder_name, build_number, step_name, |
| 293 test_name, status=analysis_status.COMPLETED |
| 294 ) |
| 295 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 296 build_number, step_name, test_name) |
| 297 analysis.success_rates.append(.50) |
| 298 analysis.build_numbers.append(100) |
| 115 analysis.put() | 299 analysis.put() |
| 116 | 300 |
| 117 queue_name = {'x': False} | 301 queue_name = {'x': False} |
| 118 | 302 def my_mocked_run(arg1, queue_name): # pylint: disable=unused-argument |
| 119 # Unused argument (class method calls in python) - pylint: disable=W0613 | |
| 120 def my_mocked_run(*_): | |
| 121 queue_name['x'] = True # pragma: no cover | 303 queue_name['x'] = True # pragma: no cover |
| 122 | 304 |
| 123 self.mock( | 305 self.mock( |
| 124 recursive_flake_pipeline.RecursiveFlakePipeline, 'start', my_mocked_run) | 306 recursive_flake_pipeline.RecursiveFlakePipeline, 'start', my_mocked_run) |
| 125 NextBuildNumberPipeline.run( | 307 NextBuildNumberPipeline.run( |
| 126 NextBuildNumberPipeline(), master_name, builder_name, | 308 NextBuildNumberPipeline(), master_name, builder_name, |
| 127 master_build_number, step_name, test_name, test_result_future, | 309 master_build_number, build_number, step_name, test_name, |
| 128 queue_name) | 310 test_result_future, queue_name, algo_dict) |
| 129 self.assertFalse(queue_name['x']) | 311 self.assertFalse(queue_name['x']) |
| 312 |
| 313 def testNextBuildPipelineForFailedSwarmingTask(self): |
| 314 master_name = 'm' |
| 315 builder_name = 'b' |
| 316 master_build_number = 100 |
| 317 build_number = 100 |
| 318 step_name = 's' |
| 319 test_name = 't' |
| 320 test_result_future = 'trf' |
| 321 queue_name = constants.DEFAULT_QUEUE |
| 322 algo_dict = { |
| 323 'flakes_in_a_row': 0, |
| 324 'stable_in_a_row': 0, |
| 325 'stabled_out': False, |
| 326 'flaked_out': False, |
| 327 'last_build_number': 0 |
| 328 } |
| 329 self._CreateAndSaveMasterFlakeAnalysis( |
| 330 master_name, builder_name, build_number, step_name, |
| 331 test_name, status=analysis_status.PENDING |
| 332 ) |
| 333 self._CreateAndSaveFlakeSwarmingTask( |
| 334 master_name, builder_name, build_number, step_name, |
| 335 test_name, status=analysis_status.ERROR |
| 336 ) |
| 337 analysis = MasterFlakeAnalysis.Get(master_name, builder_name, |
| 338 build_number, step_name, test_name) |
| 339 analysis.success_rates.append(.50) |
| 340 analysis.build_numbers.append(100) |
| 341 analysis.put() |
| 342 |
| 343 queue_name = {'x': False} |
| 344 def my_mocked_run(arg1, queue_name): # pylint: disable=unused-argument |
| 345 queue_name['x'] = True # pragma: no cover |
| 346 |
| 347 self.mock( |
| 348 recursive_flake_pipeline.RecursiveFlakePipeline, 'start', my_mocked_run) |
| 349 NextBuildNumberPipeline.run( |
| 350 NextBuildNumberPipeline(), master_name, builder_name, |
| 351 master_build_number, build_number, step_name, test_name, |
| 352 test_result_future, queue_name, algo_dict) |
| 353 self.assertFalse(queue_name['x']) |
| OLD | NEW |