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 |