Chromium Code Reviews| Index: scripts/slave/recipe_modules/auto_bisect/config_validation.py |
| diff --git a/scripts/slave/recipe_modules/auto_bisect/config_validation.py b/scripts/slave/recipe_modules/auto_bisect/config_validation.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4816cb19495747bc68b99fcf8f7180eee15443fd |
| --- /dev/null |
| +++ b/scripts/slave/recipe_modules/auto_bisect/config_validation.py |
| @@ -0,0 +1,84 @@ |
| +# 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. |
| + |
| +import re |
| + |
| +_BISECT_CONFIG_SCHEMA = { |
| + 'command': {'type': 'string', 'required': True}, |
| + 'good_revision': {'type': 'revision', 'required': True}, |
| + 'bad_revision': {'type': 'revision', 'required': True}, |
| + 'bisect_bot': {'type': 'string'}, |
| + 'metric': {'type': 'string'}, |
| + 'bug_id': {'type': 'integer'}, |
| + 'repeat_count': {'type': 'integer'}, |
| + 'max_time_minutes': {'type': 'integer'}, |
| + 'truncate_percent': {'type': 'integer'}, |
| + 'bisect_mode': {'type': 'string', |
| + 'choices': ['mean', 'return_code', 'std_dev']}, |
| + 'gs_bucket': {'type': 'string'}, |
| + 'builder_host': {'type': 'string'}, |
| + 'builder_port': {'type': 'integer'}, |
| + 'test_type': {'type': 'string'}, |
| + 'improvement_direction': {'type': 'integer'}, |
| + 'recipe_tester_name': {'type': 'string'}, |
| + 'try_job_id': {'type': 'integer'}, |
|
qyearsley
2016/03/11 01:41:34
Anything else that should be added? Or anything th
RobertoCN
2016/03/14 01:26:23
Metric could be required if the bisect_mode is mea
qyearsley
2016/03/18 22:50:19
Check for metric added; truncate_percent removed f
|
| +} |
| + |
| + |
| +class ValidationFail(Exception): |
| + """An exception class that represents a failure to validate.""" |
| + |
| + |
| +def validate_config(config, schema=None): |
| + """Checks the correctness of the given bisect job config.""" |
| + schema = _BISECT_CONFIG_SCHEMA if schema is None else schema |
| + for key in set(schema): |
| + validate_key(config, schema, key) |
|
qyearsley
2016/03/11 01:41:34
Potentially to be added: check revision order and
RobertoCN
2016/03/14 01:26:23
could also check for well-formedness of gs locatio
qyearsley
2016/03/18 22:50:19
In most bisect configs, there aren't any gs URLs,
|
| + |
| + |
| +def validate_key(config, schema, key): |
| + """Checks the correctness of the given field in a config.""" |
| + if schema[key].get('required') and key not in config: |
| + raise ValidationFail('Required key "%s" missing.' % key) |
| + if key not in config: |
| + return # Optional field. |
| + value = config[key] |
| + field_type = schema[key].get('type') |
| + if field_type == 'string': |
| + _validate_string(value, key) |
| + elif field_type == 'integer': |
| + _validate_integer(value, key) |
| + elif field_type == 'revision': |
| + _validate_revision(value, key) |
| + elif field_type == 'boolean': |
| + _validate_boolean(value, key) |
| + if 'choices' in schema[key] and value not in schema[key]['choices']: |
| + _fail(value, key) |
| + |
| + |
| +def _fail(value, key): |
| + raise ValidationFail('Invalid value %r for "%s".' % (value, key)) |
| + |
| + |
| +def _validate_string(value, key): |
| + if not isinstance(value, basestring): |
| + _fail(value, key) |
| + |
| + |
| +def _validate_revision(value, key): |
| + s = str(value) |
| + if not (s.isdigit() or re.match('^[0-9A-Fa-f]{40}$', s)): |
| + _fail(value, key) |
| + |
| + |
| +def _validate_integer(value, key): |
| + try: |
| + int(value) |
| + except ValueError: |
| + _fail(value, key) |
| + |
| + |
| +def _validate_boolean(value, key): |
| + if value not in (True, False): |
| + _fail(value, key) |