| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Provides test coverage for common recipe configurations. | 6 """Provides test coverage for common recipe configurations. |
| 7 | 7 |
| 8 recipe config expectations are located in ../recipe_configs_test/*.expected | 8 recipe config expectations are located in ../recipe_configs_test/*.expected |
| 9 | 9 |
| 10 In training mode, this will loop over every config item in ../recipe_configs.py | 10 In training mode, this will loop over every config item in ../recipe_configs.py |
| 11 crossed with every platform, and spit out the as_json() representation to | 11 crossed with every platform, and spit out the as_json() representation to |
| 12 ../recipe_configs_test | 12 ../recipe_configs_test |
| 13 | 13 |
| 14 You must have 100% coverage of ../recipe_configs.py for this test to pass. | 14 You must have 100% coverage of ../recipe_configs.py for this test to pass. |
| 15 """ | 15 """ |
| 16 | 16 |
| 17 import json | 17 import json |
| 18 import multiprocessing | 18 import multiprocessing |
| 19 import os | 19 import os |
| 20 import sys | 20 import sys |
| 21 import unittest | 21 import unittest |
| 22 from itertools import product, imap | 22 from itertools import product, imap |
| 23 | 23 |
| 24 import test_env # pylint: disable=W0611,F0401 | 24 import test_env # pylint: disable=W0611,F0401 |
| 25 | 25 |
| 26 from slave import recipe_api | 26 from slave import recipe_loader |
| 27 from slave import annotated_run | 27 from slave import recipe_util |
| 28 | 28 |
| 29 import coverage | 29 import coverage |
| 30 | 30 |
| 31 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) | 31 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) |
| 32 SLAVE_DIR = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir)) | 32 SLAVE_DIR = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir)) |
| 33 | 33 |
| 34 COVERAGE = (lambda: coverage.coverage( | 34 COVERAGE = (lambda: coverage.coverage( |
| 35 include=[os.path.join(x, '*', '*config.py') | 35 include=[os.path.join(x, '*', '*config.py') |
| 36 for x in annotated_run.MODULE_DIRS], | 36 for x in recipe_util.MODULE_DIRS()], |
| 37 data_suffix=True))() | 37 data_suffix=True))() |
| 38 | 38 |
| 39 def covered(fn, *args, **kwargs): | 39 def covered(fn, *args, **kwargs): |
| 40 COVERAGE.start() | 40 COVERAGE.start() |
| 41 try: | 41 try: |
| 42 return fn(*args, **kwargs) | 42 return fn(*args, **kwargs) |
| 43 finally: | 43 finally: |
| 44 COVERAGE.stop() | 44 COVERAGE.stop() |
| 45 | 45 |
| 46 RECIPE_MODULES = None | 46 RECIPE_MODULES = None |
| 47 def init_recipe_modules(): | 47 def init_recipe_modules(): |
| 48 global RECIPE_MODULES | 48 global RECIPE_MODULES |
| 49 RECIPE_MODULES = covered(recipe_api.load_recipe_modules, | 49 RECIPE_MODULES = covered(recipe_loader.load_recipe_modules, |
| 50 annotated_run.MODULE_DIRS) | 50 recipe_util.MODULE_DIRS()) |
| 51 | 51 |
| 52 from slave import recipe_configs_util # pylint: disable=F0401 | 52 from slave import recipe_config # pylint: disable=F0401 |
| 53 | 53 |
| 54 def get_expect_dir(mod): | 54 def get_expect_dir(mod): |
| 55 return os.path.join(mod.__path__[0], 'config.expected') | 55 return os.path.join(mod.__path__[0], 'config.expected') |
| 56 | 56 |
| 57 | 57 |
| 58 def evaluate_configurations(args): | 58 def evaluate_configurations(args): |
| 59 mod_id, var_assignments = args | 59 mod_id, var_assignments = args |
| 60 mod = getattr(RECIPE_MODULES, mod_id) | 60 mod = getattr(RECIPE_MODULES, mod_id) |
| 61 expect_dir = get_expect_dir(mod) | 61 expect_dir = get_expect_dir(mod) |
| 62 ctx = mod.CONFIG_CTX | 62 ctx = mod.CONFIG_CTX |
| 63 | 63 |
| 64 config_name = None | 64 config_name = None |
| 65 try: | 65 try: |
| 66 file_name = os.path.join(expect_dir, ctx.TEST_FILE_FORMAT(var_assignments)) | 66 file_name = os.path.join(expect_dir, ctx.TEST_FILE_FORMAT(var_assignments)) |
| 67 ret = {} | 67 ret = {} |
| 68 | 68 |
| 69 make_item = lambda: covered(ctx.CONFIG_SCHEMA, **var_assignments) | 69 make_item = lambda: covered(ctx.CONFIG_SCHEMA, **var_assignments) |
| 70 | 70 |
| 71 # Try ROOT_CONFIG_ITEM first. If it raises BadConf, then we can skip | 71 # Try ROOT_CONFIG_ITEM first. If it raises BadConf, then we can skip |
| 72 # this config. | 72 # this config. |
| 73 root_item = ctx.ROOT_CONFIG_ITEM | 73 root_item = ctx.ROOT_CONFIG_ITEM |
| 74 if root_item: | 74 if root_item: |
| 75 config_name = root_item.__name__ | 75 config_name = root_item.__name__ |
| 76 try: | 76 try: |
| 77 result = covered(root_item, make_item()) | 77 result = covered(root_item, make_item()) |
| 78 if result.complete(): | 78 if result.complete(): |
| 79 ret[config_name] = result.as_jsonish() | 79 ret[config_name] = result.as_jsonish() |
| 80 except recipe_configs_util.BadConf, e: | 80 except recipe_config.BadConf, e: |
| 81 return file_name, None, None | 81 return file_name, None, None |
| 82 | 82 |
| 83 for config_name, fn in ctx.CONFIG_ITEMS.iteritems(): | 83 for config_name, fn in ctx.CONFIG_ITEMS.iteritems(): |
| 84 if fn.NO_TEST or fn.IS_ROOT: | 84 if fn.NO_TEST or fn.IS_ROOT: |
| 85 continue | 85 continue |
| 86 try: | 86 try: |
| 87 result = covered(fn, make_item()) | 87 result = covered(fn, make_item()) |
| 88 if result.complete(): | 88 if result.complete(): |
| 89 ret[config_name] = result.as_jsonish() | 89 ret[config_name] = result.as_jsonish() |
| 90 except recipe_configs_util.BadConf, e: | 90 except recipe_config.BadConf, e: |
| 91 ret[config_name] = str(e) | 91 ret[config_name] = str(e) |
| 92 return file_name, covered(ctx.TEST_NAME_FORMAT, var_assignments), ret | 92 return file_name, covered(ctx.TEST_NAME_FORMAT, var_assignments), ret |
| 93 except Exception, e: | 93 except Exception, e: |
| 94 print 'Caught exception [%s] with args %s: %s' % (e, args, config_name) | 94 print 'Caught exception [%s] with args %s: %s' % (e, args, config_name) |
| 95 | 95 |
| 96 | 96 |
| 97 def train_from_tests(args): | 97 def train_from_tests(args): |
| 98 file_name, _, configuration_results = evaluate_configurations(args) | 98 file_name, _, configuration_results = evaluate_configurations(args) |
| 99 if configuration_results is not None: | 99 if configuration_results is not None: |
| 100 if configuration_results: | 100 if configuration_results: |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 retcode = retcode or 2 | 233 retcode = retcode or 2 |
| 234 | 234 |
| 235 if training: | 235 if training: |
| 236 test_env.print_coverage_warning() | 236 test_env.print_coverage_warning() |
| 237 | 237 |
| 238 return retcode | 238 return retcode |
| 239 | 239 |
| 240 | 240 |
| 241 if __name__ == '__main__': | 241 if __name__ == '__main__': |
| 242 sys.exit(main(sys.argv)) | 242 sys.exit(main(sys.argv)) |
| OLD | NEW |