# Copyright 2016 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. """A handler and functions to check whether bisect is supported.""" import re from dashboard import request_handler from dashboard import namespaced_stored_object # A set of suites for which we can't do performance bisects. # This list currently also exists in the front-end code. _UNBISECTABLE_SUITES = [ 'arc-perf-test', 'browser_tests', 'content_browsertests', 'resource_sizes', 'sizes', 'v8', ] # The bisect bot map stored in datastore is expected to be # a dict mapping master names to [perf bot, bisect bot] pairs. # If a master name is not in the dict, bisect isn't supported. BISECT_BOT_MAP_KEY = 'bisect_bot_map' class CanBisectHandler(request_handler.RequestHandler): def post(self): """Checks whether bisect is supported for a test. Request parameters: test_path: A full test path (Master/bot/benchmark/...) start_revision: The start of the bisect revision range. end_revision: The end of the bisect revision range. Outputs: The string "true" or the string "false". """ can_bisect = ( IsValidTestForBisect(self.request.get('test_path')) and IsValidRevisionForBisect(self.request.get('start_revision')) and IsValidRevisionForBisect(self.request.get('end_revision'))) self.response.write('true' if can_bisect else 'false') def IsValidTestForBisect(test_path): """Checks whether a test is valid for bisect.""" if not test_path: return False path_parts = test_path.split('/') if len(path_parts) < 3: return False if not _MasterNameIsWhitelisted(path_parts[0]): return False if path_parts[2] in _UNBISECTABLE_SUITES: return False if test_path.endswith('/ref') or test_path.endswith('_ref'): return False return True def _MasterNameIsWhitelisted(master_name): """Checks whether a master name is acceptable by checking a whitelist.""" bisect_bot_map = namespaced_stored_object.Get(BISECT_BOT_MAP_KEY) if not bisect_bot_map: return True # If there's no list available, all names are OK. whitelisted_masters = list(bisect_bot_map) return master_name in whitelisted_masters def IsValidRevisionForBisect(revision): """Checks whether a revision looks like a valid revision for bisect.""" return _IsGitHash(revision) or re.match(r'^[0-9]{5,7}$', str(revision)) def _IsGitHash(revision): """Checks whether the input looks like a SHA1 hash.""" return re.match(r'[a-fA-F0-9]{40}$', str(revision))