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 3# found in the LICENSE file. 4 5"""A handler and functions to check whether bisect is supported.""" 6 7import re 8 9from dashboard import request_handler 10from dashboard import namespaced_stored_object 11 12# A set of suites for which we can't do performance bisects. 13# This list currently also exists in the front-end code. 14_UNBISECTABLE_SUITES = [ 15 'arc-perf-test', 16 'browser_tests', 17 'content_browsertests', 18 'resource_sizes', 19 'sizes', 20 'v8', 21] 22 23# The bisect bot map stored in datastore is expected to be 24# a dict mapping master names to [perf bot, bisect bot] pairs. 25# If a master name is not in the dict, bisect isn't supported. 26BISECT_BOT_MAP_KEY = 'bisect_bot_map' 27 28 29class CanBisectHandler(request_handler.RequestHandler): 30 31 def post(self): 32 """Checks whether bisect is supported for a test. 33 34 Request parameters: 35 test_path: A full test path (Master/bot/benchmark/...) 36 start_revision: The start of the bisect revision range. 37 end_revision: The end of the bisect revision range. 38 39 Outputs: The string "true" or the string "false". 40 """ 41 can_bisect = ( 42 IsValidTestForBisect(self.request.get('test_path')) and 43 IsValidRevisionForBisect(self.request.get('start_revision')) and 44 IsValidRevisionForBisect(self.request.get('end_revision'))) 45 self.response.write('true' if can_bisect else 'false') 46 47 48def IsValidTestForBisect(test_path): 49 """Checks whether a test is valid for bisect.""" 50 if not test_path: 51 return False 52 path_parts = test_path.split('/') 53 if len(path_parts) < 3: 54 return False 55 if not _MasterNameIsWhitelisted(path_parts[0]): 56 return False 57 if path_parts[2] in _UNBISECTABLE_SUITES: 58 return False 59 if test_path.endswith('/ref') or test_path.endswith('_ref'): 60 return False 61 return True 62 63 64def _MasterNameIsWhitelisted(master_name): 65 """Checks whether a master name is acceptable by checking a whitelist.""" 66 bisect_bot_map = namespaced_stored_object.Get(BISECT_BOT_MAP_KEY) 67 if not bisect_bot_map: 68 return True # If there's no list available, all names are OK. 69 whitelisted_masters = list(bisect_bot_map) 70 return master_name in whitelisted_masters 71 72 73def IsValidRevisionForBisect(revision): 74 """Checks whether a revision looks like a valid revision for bisect.""" 75 return _IsGitHash(revision) or re.match(r'^[0-9]{5,7}$', str(revision)) 76 77 78def _IsGitHash(revision): 79 """Checks whether the input looks like a SHA1 hash.""" 80 return re.match(r'[a-fA-F0-9]{40}$', str(revision)) 81