| 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_loader | 26 from slave import recipe_loader |
| 27 from slave import recipe_util | 27 from slave import recipe_util |
| 28 from slave import recipe_config_types |
| 28 | 29 |
| 29 import coverage | 30 import coverage |
| 30 | 31 |
| 31 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) | 32 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) |
| 32 SLAVE_DIR = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir)) | 33 SLAVE_DIR = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir)) |
| 33 | 34 |
| 34 COVERAGE = (lambda: coverage.coverage( | 35 COVERAGE = (lambda: coverage.coverage( |
| 35 include=[os.path.join(x, '*', '*config.py') | 36 include=[os.path.join(x, '*', '*config.py') |
| 36 for x in recipe_util.MODULE_DIRS()], | 37 for x in recipe_util.MODULE_DIRS()], |
| 37 data_suffix=True))() | 38 data_suffix=True))() |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 except Exception, e: | 94 except Exception, e: |
| 94 print 'Caught exception [%s] with args %s: %s' % (e, args, config_name) | 95 print 'Caught exception [%s] with args %s: %s' % (e, args, config_name) |
| 95 | 96 |
| 96 | 97 |
| 97 def train_from_tests(args): | 98 def train_from_tests(args): |
| 98 file_name, _, configuration_results = evaluate_configurations(args) | 99 file_name, _, configuration_results = evaluate_configurations(args) |
| 99 if configuration_results is not None: | 100 if configuration_results is not None: |
| 100 if configuration_results: | 101 if configuration_results: |
| 101 print 'Writing', file_name | 102 print 'Writing', file_name |
| 102 with open(file_name, 'wb') as f: | 103 with open(file_name, 'wb') as f: |
| 103 json.dump(configuration_results, f, sort_keys=True, indent=2) | 104 json.dump(configuration_results, f, sort_keys=True, indent=2, |
| 105 default=recipe_config_types.json_fixup) |
| 104 else: | 106 else: |
| 105 print 'Empty', file_name | 107 print 'Empty', file_name |
| 106 | 108 |
| 107 if not configuration_results: # None or {} | 109 if not configuration_results: # None or {} |
| 108 if os.path.exists(file_name): | 110 if os.path.exists(file_name): |
| 109 os.unlink(file_name) | 111 os.unlink(file_name) |
| 110 return True | 112 return True |
| 111 | 113 |
| 112 | 114 |
| 113 def load_tests(loader, _standard_tests, _pattern): | 115 def load_tests(loader, _standard_tests, _pattern): |
| (...skipping 10 matching lines...) Expand all Loading... |
| 124 | 126 |
| 125 class RecipeConfigsTest(unittest.TestCase): | 127 class RecipeConfigsTest(unittest.TestCase): |
| 126 def testNoLeftovers(self): | 128 def testNoLeftovers(self): |
| 127 """add_test_methods() should completely drain json_expectation.""" | 129 """add_test_methods() should completely drain json_expectation.""" |
| 128 self.assertEqual(json_expectation, {}) | 130 self.assertEqual(json_expectation, {}) |
| 129 | 131 |
| 130 @classmethod | 132 @classmethod |
| 131 def add_test_methods(cls): | 133 def add_test_methods(cls): |
| 132 for name, result in configuration_results.iteritems(): | 134 for name, result in configuration_results.iteritems(): |
| 133 def add_test(name, result, expected_result): | 135 def add_test(name, result, expected_result): |
| 136 # Roundtrip json to get same string encoding as load |
| 137 result = json.loads( |
| 138 json.dumps(result, default=recipe_config_types.json_fixup)) |
| 134 def test_(self): | 139 def test_(self): |
| 135 self.assertEqual(result, expected_result) | 140 self.assertEqual(result, expected_result) |
| 136 test_.__name__ += name | 141 test_.__name__ += name |
| 137 setattr(cls, test_.__name__, test_) | 142 setattr(cls, test_.__name__, test_) |
| 138 add_test(name, result, json_expectation.pop(name, {})) | 143 add_test(name, result, json_expectation.pop(name, {})) |
| 139 | 144 |
| 140 RecipeConfigsTest.add_test_methods() | 145 RecipeConfigsTest.add_test_methods() |
| 141 | 146 |
| 142 RecipeConfigsTest.__name__ += test_name_suffix | 147 RecipeConfigsTest.__name__ += test_name_suffix |
| 143 return RecipeConfigsTest | 148 return RecipeConfigsTest |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 retcode = retcode or 2 | 238 retcode = retcode or 2 |
| 234 | 239 |
| 235 if training: | 240 if training: |
| 236 test_env.print_coverage_warning() | 241 test_env.print_coverage_warning() |
| 237 | 242 |
| 238 return retcode | 243 return retcode |
| 239 | 244 |
| 240 | 245 |
| 241 if __name__ == '__main__': | 246 if __name__ == '__main__': |
| 242 sys.exit(main(sys.argv)) | 247 sys.exit(main(sys.argv)) |
| OLD | NEW |